PostgreSQL Source Code  git master
hmac.c File Reference
#include "postgres.h"
#include "common/cryptohash.h"
#include "common/hmac.h"
#include "common/md5.h"
#include "common/sha1.h"
#include "common/sha2.h"
Include dependency graph for hmac.c:

Go to the source code of this file.

Data Structures

struct  pg_hmac_ctx
 

Macros

#define ALLOC(size)   palloc(size)
 
#define FREE(ptr)   pfree(ptr)
 
#define HMAC_IPAD   0x36
 
#define HMAC_OPAD   0x5C
 

Typedefs

typedef enum pg_hmac_errno pg_hmac_errno
 

Enumerations

enum  pg_hmac_errno {
  PG_HMAC_ERROR_NONE = 0 , PG_HMAC_ERROR_OOM , PG_HMAC_ERROR_INTERNAL , PG_HMAC_ERROR_NONE = 0 ,
  PG_HMAC_ERROR_DEST_LEN , PG_HMAC_ERROR_OPENSSL
}
 

Functions

pg_hmac_ctxpg_hmac_create (pg_cryptohash_type type)
 
int pg_hmac_init (pg_hmac_ctx *ctx, const uint8 *key, size_t len)
 
int pg_hmac_update (pg_hmac_ctx *ctx, const uint8 *data, size_t len)
 
int pg_hmac_final (pg_hmac_ctx *ctx, uint8 *dest, size_t len)
 
void pg_hmac_free (pg_hmac_ctx *ctx)
 
const char * pg_hmac_error (pg_hmac_ctx *ctx)
 

Macro Definition Documentation

◆ ALLOC

#define ALLOC (   size)    palloc(size)

Definition at line 34 of file hmac.c.

◆ FREE

#define FREE (   ptr)    pfree(ptr)

Definition at line 35 of file hmac.c.

◆ HMAC_IPAD

#define HMAC_IPAD   0x36

Definition at line 67 of file hmac.c.

◆ HMAC_OPAD

#define HMAC_OPAD   0x5C

Definition at line 68 of file hmac.c.

Typedef Documentation

◆ pg_hmac_errno

Enumeration Type Documentation

◆ pg_hmac_errno

Enumerator
PG_HMAC_ERROR_NONE 
PG_HMAC_ERROR_OOM 
PG_HMAC_ERROR_INTERNAL 
PG_HMAC_ERROR_NONE 
PG_HMAC_ERROR_DEST_LEN 
PG_HMAC_ERROR_OPENSSL 

Definition at line 42 of file hmac.c.

43 {
pg_hmac_errno
Definition: hmac.c:43
@ PG_HMAC_ERROR_INTERNAL
Definition: hmac.c:46
@ PG_HMAC_ERROR_OOM
Definition: hmac.c:45
@ PG_HMAC_ERROR_NONE
Definition: hmac.c:44

Function Documentation

◆ pg_hmac_create()

pg_hmac_ctx* pg_hmac_create ( pg_cryptohash_type  type)

Definition at line 77 of file hmac.c.

78 {
79  pg_hmac_ctx *ctx;
80 
81  ctx = ALLOC(sizeof(pg_hmac_ctx));
82  if (ctx == NULL)
83  return NULL;
84  memset(ctx, 0, sizeof(pg_hmac_ctx));
85  ctx->type = type;
87  ctx->errreason = NULL;
88 
89  /*
90  * Initialize the context data. This requires to know the digest and
91  * block lengths, that depend on the type of hash used.
92  */
93  switch (type)
94  {
95  case PG_MD5:
98  break;
99  case PG_SHA1:
102  break;
103  case PG_SHA224:
106  break;
107  case PG_SHA256:
110  break;
111  case PG_SHA384:
114  break;
115  case PG_SHA512:
118  break;
119  }
120 
122  if (ctx->hash == NULL)
123  {
124  explicit_bzero(ctx, sizeof(pg_hmac_ctx));
125  FREE(ctx);
126  return NULL;
127  }
128 
129  return ctx;
130 }
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:74
@ PG_SHA512
Definition: cryptohash.h:26
@ PG_SHA224
Definition: cryptohash.h:23
@ PG_SHA384
Definition: cryptohash.h:25
@ PG_SHA1
Definition: cryptohash.h:22
@ PG_SHA256
Definition: cryptohash.h:24
@ PG_MD5
Definition: cryptohash.h:21
#define FREE(ptr)
Definition: hmac.c:35
#define ALLOC(size)
Definition: hmac.c:34
#define MD5_DIGEST_LENGTH
Definition: md5.h:20
#define MD5_BLOCK_SIZE
Definition: md5.h:22
void explicit_bzero(void *buf, size_t len)
#define SHA1_DIGEST_LENGTH
Definition: sha1.h:17
#define SHA1_BLOCK_SIZE
Definition: sha1.h:19
#define PG_SHA256_DIGEST_LENGTH
Definition: sha2.h:23
#define PG_SHA384_BLOCK_LENGTH
Definition: sha2.h:25
#define PG_SHA384_DIGEST_LENGTH
Definition: sha2.h:26
#define PG_SHA512_DIGEST_LENGTH
Definition: sha2.h:29
#define PG_SHA256_BLOCK_LENGTH
Definition: sha2.h:22
#define PG_SHA512_BLOCK_LENGTH
Definition: sha2.h:28
#define PG_SHA224_BLOCK_LENGTH
Definition: sha2.h:19
#define PG_SHA224_DIGEST_LENGTH
Definition: sha2.h:20
const char * errreason
Definition: hmac.c:55
pg_cryptohash_ctx * hash
Definition: hmac.c:52
int digest_size
Definition: hmac.c:57
int block_size
Definition: hmac.c:56
pg_cryptohash_type type
Definition: hmac.c:53
pg_hmac_errno error
Definition: hmac.c:54
const char * type

References ALLOC, pg_hmac_ctx::block_size, pg_hmac_ctx::digest_size, pg_hmac_ctx::error, pg_hmac_ctx::errreason, explicit_bzero(), FREE, pg_hmac_ctx::hash, MD5_BLOCK_SIZE, MD5_DIGEST_LENGTH, pg_cryptohash_create(), PG_HMAC_ERROR_NONE, PG_MD5, PG_SHA1, PG_SHA224, PG_SHA224_BLOCK_LENGTH, PG_SHA224_DIGEST_LENGTH, PG_SHA256, PG_SHA256_BLOCK_LENGTH, PG_SHA256_DIGEST_LENGTH, PG_SHA384, PG_SHA384_BLOCK_LENGTH, PG_SHA384_DIGEST_LENGTH, PG_SHA512, PG_SHA512_BLOCK_LENGTH, PG_SHA512_DIGEST_LENGTH, SHA1_BLOCK_SIZE, SHA1_DIGEST_LENGTH, type, and pg_hmac_ctx::type.

Referenced by build_server_final_message(), calculate_client_proof(), scram_ClientKey(), scram_SaltedPassword(), scram_ServerKey(), verify_client_proof(), and verify_server_signature().

◆ pg_hmac_error()

const char* pg_hmac_error ( pg_hmac_ctx ctx)

Definition at line 306 of file hmac.c.

307 {
308  if (ctx == NULL)
309  return _("out of memory");
310 
311  /*
312  * If a reason is provided, rely on it, else fallback to any error code
313  * set.
314  */
315  if (ctx->errreason)
316  return ctx->errreason;
317 
318  switch (ctx->error)
319  {
320  case PG_HMAC_ERROR_NONE:
321  return _("success");
323  return _("internal error");
324  case PG_HMAC_ERROR_OOM:
325  return _("out of memory");
326  }
327 
328  Assert(false); /* cannot be reached */
329  return _("success");
330 }
#define Assert(condition)
Definition: c.h:858
#define _(x)
Definition: elog.c:90

References _, Assert, pg_hmac_ctx::error, pg_hmac_ctx::errreason, PG_HMAC_ERROR_INTERNAL, PG_HMAC_ERROR_NONE, and PG_HMAC_ERROR_OOM.

Referenced by build_server_final_message(), calculate_client_proof(), scram_ClientKey(), scram_SaltedPassword(), scram_ServerKey(), verify_client_proof(), and verify_server_signature().

◆ pg_hmac_final()

int pg_hmac_final ( pg_hmac_ctx ctx,
uint8 dest,
size_t  len 
)

Definition at line 244 of file hmac.c.

245 {
246  uint8 *h;
247 
248  if (ctx == NULL)
249  return -1;
250 
251  h = ALLOC(ctx->digest_size);
252  if (h == NULL)
253  {
254  ctx->error = PG_HMAC_ERROR_OOM;
255  return -1;
256  }
257  memset(h, 0, ctx->digest_size);
258 
259  if (pg_cryptohash_final(ctx->hash, h, ctx->digest_size) < 0)
260  {
262  ctx->errreason = pg_cryptohash_error(ctx->hash);
263  FREE(h);
264  return -1;
265  }
266 
267  /* H(K XOR opad, tmp) */
268  if (pg_cryptohash_init(ctx->hash) < 0 ||
269  pg_cryptohash_update(ctx->hash, ctx->k_opad, ctx->block_size) < 0 ||
270  pg_cryptohash_update(ctx->hash, h, ctx->digest_size) < 0 ||
271  pg_cryptohash_final(ctx->hash, dest, len) < 0)
272  {
274  ctx->errreason = pg_cryptohash_error(ctx->hash);
275  FREE(h);
276  return -1;
277  }
278 
279  FREE(h);
280  return 0;
281 }
unsigned char uint8
Definition: c.h:504
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:136
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:100
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:172
const char * pg_cryptohash_error(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:254
const void size_t len
uint8 k_opad[PG_SHA512_BLOCK_LENGTH]
Definition: hmac.c:64

References ALLOC, pg_hmac_ctx::block_size, generate_unaccent_rules::dest, pg_hmac_ctx::digest_size, pg_hmac_ctx::error, pg_hmac_ctx::errreason, FREE, pg_hmac_ctx::hash, pg_hmac_ctx::k_opad, len, pg_cryptohash_error(), pg_cryptohash_final(), pg_cryptohash_init(), pg_cryptohash_update(), PG_HMAC_ERROR_INTERNAL, and PG_HMAC_ERROR_OOM.

Referenced by build_server_final_message(), calculate_client_proof(), scram_ClientKey(), scram_SaltedPassword(), scram_ServerKey(), verify_client_proof(), and verify_server_signature().

◆ pg_hmac_free()

void pg_hmac_free ( pg_hmac_ctx ctx)

Definition at line 289 of file hmac.c.

290 {
291  if (ctx == NULL)
292  return;
293 
294  pg_cryptohash_free(ctx->hash);
295  explicit_bzero(ctx, sizeof(pg_hmac_ctx));
296  FREE(ctx);
297 }
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:238

References explicit_bzero(), FREE, pg_hmac_ctx::hash, and pg_cryptohash_free().

Referenced by build_server_final_message(), calculate_client_proof(), scram_ClientKey(), scram_SaltedPassword(), scram_ServerKey(), verify_client_proof(), and verify_server_signature().

◆ pg_hmac_init()

int pg_hmac_init ( pg_hmac_ctx ctx,
const uint8 key,
size_t  len 
)

Definition at line 138 of file hmac.c.

139 {
140  int i;
141  int digest_size;
142  int block_size;
143  uint8 *shrinkbuf = NULL;
144 
145  if (ctx == NULL)
146  return -1;
147 
148  digest_size = ctx->digest_size;
149  block_size = ctx->block_size;
150 
151  memset(ctx->k_opad, HMAC_OPAD, ctx->block_size);
152  memset(ctx->k_ipad, HMAC_IPAD, ctx->block_size);
153 
154  /*
155  * If the key is longer than the block size, pass it through the hash once
156  * to shrink it down.
157  */
158  if (len > block_size)
159  {
160  pg_cryptohash_ctx *hash_ctx;
161 
162  /* temporary buffer for one-time shrink */
163  shrinkbuf = ALLOC(digest_size);
164  if (shrinkbuf == NULL)
165  {
166  ctx->error = PG_HMAC_ERROR_OOM;
167  return -1;
168  }
169  memset(shrinkbuf, 0, digest_size);
170 
171  hash_ctx = pg_cryptohash_create(ctx->type);
172  if (hash_ctx == NULL)
173  {
174  ctx->error = PG_HMAC_ERROR_OOM;
175  FREE(shrinkbuf);
176  return -1;
177  }
178 
179  if (pg_cryptohash_init(hash_ctx) < 0 ||
180  pg_cryptohash_update(hash_ctx, key, len) < 0 ||
181  pg_cryptohash_final(hash_ctx, shrinkbuf, digest_size) < 0)
182  {
184  ctx->errreason = pg_cryptohash_error(hash_ctx);
185  pg_cryptohash_free(hash_ctx);
186  FREE(shrinkbuf);
187  return -1;
188  }
189 
190  key = shrinkbuf;
191  len = digest_size;
192  pg_cryptohash_free(hash_ctx);
193  }
194 
195  for (i = 0; i < len; i++)
196  {
197  ctx->k_ipad[i] ^= key[i];
198  ctx->k_opad[i] ^= key[i];
199  }
200 
201  /* tmp = H(K XOR ipad, text) */
202  if (pg_cryptohash_init(ctx->hash) < 0 ||
203  pg_cryptohash_update(ctx->hash, ctx->k_ipad, ctx->block_size) < 0)
204  {
206  ctx->errreason = pg_cryptohash_error(ctx->hash);
207  if (shrinkbuf)
208  FREE(shrinkbuf);
209  return -1;
210  }
211 
212  if (shrinkbuf)
213  FREE(shrinkbuf);
214  return 0;
215 }
static int block_size
Definition: guc_tables.c:598
#define HMAC_OPAD
Definition: hmac.c:68
#define HMAC_IPAD
Definition: hmac.c:67
int i
Definition: isn.c:73
uint8 k_ipad[PG_SHA512_BLOCK_LENGTH]
Definition: hmac.c:63

References ALLOC, block_size, pg_hmac_ctx::block_size, pg_hmac_ctx::digest_size, pg_hmac_ctx::error, pg_hmac_ctx::errreason, FREE, pg_hmac_ctx::hash, HMAC_IPAD, HMAC_OPAD, i, pg_hmac_ctx::k_ipad, pg_hmac_ctx::k_opad, sort-test::key, len, pg_cryptohash_create(), pg_cryptohash_error(), pg_cryptohash_final(), pg_cryptohash_free(), pg_cryptohash_init(), pg_cryptohash_update(), PG_HMAC_ERROR_INTERNAL, PG_HMAC_ERROR_OOM, and pg_hmac_ctx::type.

Referenced by build_server_final_message(), calculate_client_proof(), scram_ClientKey(), scram_SaltedPassword(), scram_ServerKey(), verify_client_proof(), and verify_server_signature().

◆ pg_hmac_update()

int pg_hmac_update ( pg_hmac_ctx ctx,
const uint8 data,
size_t  len 
)

Definition at line 223 of file hmac.c.

224 {
225  if (ctx == NULL)
226  return -1;
227 
228  if (pg_cryptohash_update(ctx->hash, data, len) < 0)
229  {
231  ctx->errreason = pg_cryptohash_error(ctx->hash);
232  return -1;
233  }
234 
235  return 0;
236 }
const void * data

References data, pg_hmac_ctx::error, pg_hmac_ctx::errreason, pg_hmac_ctx::hash, len, pg_cryptohash_error(), pg_cryptohash_update(), and PG_HMAC_ERROR_INTERNAL.

Referenced by build_server_final_message(), calculate_client_proof(), scram_ClientKey(), scram_SaltedPassword(), scram_ServerKey(), verify_client_proof(), and verify_server_signature().