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
 

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)
 

Macro Definition Documentation

◆ ALLOC

#define ALLOC (   size)    palloc(size)

Definition at line 34 of file hmac.c.

Referenced by pg_hmac_create(), pg_hmac_final(), and pg_hmac_init().

◆ FREE

#define FREE (   ptr)    pfree(ptr)

Definition at line 35 of file hmac.c.

Referenced by pg_hmac_create(), pg_hmac_free(), and pg_hmac_init().

◆ HMAC_IPAD

#define HMAC_IPAD   0x36

Definition at line 59 of file hmac.c.

Referenced by pg_hmac_init().

◆ HMAC_OPAD

#define HMAC_OPAD   0x5C

Definition at line 60 of file hmac.c.

Referenced by pg_hmac_init().

Function Documentation

◆ pg_hmac_create()

pg_hmac_ctx* pg_hmac_create ( pg_cryptohash_type  type)

Definition at line 69 of file hmac.c.

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

70 {
71  pg_hmac_ctx *ctx;
72 
73  ctx = ALLOC(sizeof(pg_hmac_ctx));
74  if (ctx == NULL)
75  return NULL;
76  memset(ctx, 0, sizeof(pg_hmac_ctx));
77  ctx->type = type;
78 
79  /*
80  * Initialize the context data. This requires to know the digest and
81  * block lengths, that depend on the type of hash used.
82  */
83  switch (type)
84  {
85  case PG_MD5:
88  break;
89  case PG_SHA1:
92  break;
93  case PG_SHA224:
96  break;
97  case PG_SHA256:
100  break;
101  case PG_SHA384:
104  break;
105  case PG_SHA512:
108  break;
109  }
110 
112  if (ctx->hash == NULL)
113  {
114  explicit_bzero(ctx, sizeof(pg_hmac_ctx));
115  FREE(ctx);
116  return NULL;
117  }
118 
119  return ctx;
120 }
pg_cryptohash_ctx * hash
Definition: hmac.c:46
#define MD5_BLOCK_SIZE
Definition: internal.c:45
#define PG_SHA384_BLOCK_LENGTH
Definition: sha2.h:23
#define SHA1_DIGEST_LENGTH
Definition: sha1.h:17
#define PG_SHA256_DIGEST_LENGTH
Definition: sha2.h:22
#define PG_SHA512_DIGEST_LENGTH
Definition: sha2.h:26
#define FREE(ptr)
Definition: hmac.c:35
#define SHA1_BLOCK_SIZE
Definition: internal.c:44
#define PG_SHA256_BLOCK_LENGTH
Definition: sha2.h:21
#define MD5_DIGEST_LENGTH
Definition: md5.h:20
#define PG_SHA512_BLOCK_LENGTH
Definition: sha2.h:25
#define PG_SHA224_BLOCK_LENGTH
Definition: sha2.h:19
int digest_size
Definition: hmac.c:49
#define ALLOC(size)
Definition: hmac.c:34
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:66
int block_size
Definition: hmac.c:48
pg_cryptohash_type type
Definition: hmac.c:47
void explicit_bzero(void *buf, size_t len)
#define PG_SHA224_DIGEST_LENGTH
Definition: sha2.h:20
#define PG_SHA384_DIGEST_LENGTH
Definition: sha2.h:24

◆ pg_hmac_final()

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

Definition at line 222 of file hmac.c.

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

223 {
224  uint8 *h;
225 
226  if (ctx == NULL)
227  return -1;
228 
229  h = ALLOC(ctx->digest_size);
230  if (h == NULL)
231  return -1;
232  memset(h, 0, ctx->digest_size);
233 
234  if (pg_cryptohash_final(ctx->hash, h, ctx->digest_size) < 0)
235  return -1;
236 
237  /* H(K XOR opad, tmp) */
238  if (pg_cryptohash_init(ctx->hash) < 0 ||
239  pg_cryptohash_update(ctx->hash, ctx->k_opad, ctx->block_size) < 0 ||
240  pg_cryptohash_update(ctx->hash, h, ctx->digest_size) < 0 ||
241  pg_cryptohash_final(ctx->hash, dest, len) < 0)
242  {
243  return -1;
244  }
245 
246  return 0;
247 }
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:168
pg_cryptohash_ctx * hash
Definition: hmac.c:46
unsigned char uint8
Definition: c.h:439
uint8 k_opad[PG_SHA512_BLOCK_LENGTH]
Definition: hmac.c:56
int digest_size
Definition: hmac.c:49
#define ALLOC(size)
Definition: hmac.c:34
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:92
int block_size
Definition: hmac.c:48
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:130

◆ pg_hmac_free()

void pg_hmac_free ( pg_hmac_ctx ctx)

Definition at line 255 of file hmac.c.

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

256 {
257  if (ctx == NULL)
258  return;
259 
260  pg_cryptohash_free(ctx->hash);
261  explicit_bzero(ctx, sizeof(pg_hmac_ctx));
262  FREE(ctx);
263 }
pg_cryptohash_ctx * hash
Definition: hmac.c:46
#define FREE(ptr)
Definition: hmac.c:35
void explicit_bzero(void *buf, size_t len)
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:216

◆ pg_hmac_init()

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

Definition at line 128 of file hmac.c.

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

129 {
130  int i;
131  int digest_size;
132  int block_size;
133  uint8 *shrinkbuf = NULL;
134 
135  if (ctx == NULL)
136  return -1;
137 
138  digest_size = ctx->digest_size;
139  block_size = ctx->block_size;
140 
141  memset(ctx->k_opad, HMAC_OPAD, ctx->block_size);
142  memset(ctx->k_ipad, HMAC_IPAD, ctx->block_size);
143 
144  /*
145  * If the key is longer than the block size, pass it through the hash once
146  * to shrink it down.
147  */
148  if (len > block_size)
149  {
150  pg_cryptohash_ctx *hash_ctx;
151 
152  /* temporary buffer for one-time shrink */
153  shrinkbuf = ALLOC(digest_size);
154  if (shrinkbuf == NULL)
155  return -1;
156  memset(shrinkbuf, 0, digest_size);
157 
158  hash_ctx = pg_cryptohash_create(ctx->type);
159  if (hash_ctx == NULL)
160  {
161  FREE(shrinkbuf);
162  return -1;
163  }
164 
165  if (pg_cryptohash_init(hash_ctx) < 0 ||
166  pg_cryptohash_update(hash_ctx, key, len) < 0 ||
167  pg_cryptohash_final(hash_ctx, shrinkbuf, digest_size) < 0)
168  {
169  pg_cryptohash_free(hash_ctx);
170  FREE(shrinkbuf);
171  return -1;
172  }
173 
174  key = shrinkbuf;
175  len = digest_size;
176  pg_cryptohash_free(hash_ctx);
177  }
178 
179  for (i = 0; i < len; i++)
180  {
181  ctx->k_ipad[i] ^= key[i];
182  ctx->k_opad[i] ^= key[i];
183  }
184 
185  /* tmp = H(K XOR ipad, text) */
186  if (pg_cryptohash_init(ctx->hash) < 0 ||
187  pg_cryptohash_update(ctx->hash, ctx->k_ipad, ctx->block_size) < 0)
188  {
189  if (shrinkbuf)
190  FREE(shrinkbuf);
191  return -1;
192  }
193 
194  if (shrinkbuf)
195  FREE(shrinkbuf);
196  return 0;
197 }
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:168
pg_cryptohash_ctx * hash
Definition: hmac.c:46
static int block_size
Definition: guc.c:632
unsigned char uint8
Definition: c.h:439
#define FREE(ptr)
Definition: hmac.c:35
uint8 k_ipad[PG_SHA512_BLOCK_LENGTH]
Definition: hmac.c:55
uint8 k_opad[PG_SHA512_BLOCK_LENGTH]
Definition: hmac.c:56
int digest_size
Definition: hmac.c:49
#define ALLOC(size)
Definition: hmac.c:34
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:66
#define HMAC_OPAD
Definition: hmac.c:60
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:92
int block_size
Definition: hmac.c:48
#define HMAC_IPAD
Definition: hmac.c:59
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:130
pg_cryptohash_type type
Definition: hmac.c:47
int i
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:216

◆ pg_hmac_update()

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

Definition at line 205 of file hmac.c.

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

206 {
207  if (ctx == NULL)
208  return -1;
209 
210  if (pg_cryptohash_update(ctx->hash, data, len) < 0)
211  return -1;
212 
213  return 0;
214 }
pg_cryptohash_ctx * hash
Definition: hmac.c:46
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:130