summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/md.c244
1 files changed, 120 insertions, 124 deletions
diff --git a/cipher/md.c b/cipher/md.c
index 19b2c9bc..c6bf90d2 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -108,10 +108,9 @@ struct gcry_md_context
unsigned int secure: 1;
unsigned int finalized:1;
unsigned int bugemu1:1;
+ unsigned int hmac:1;
} flags;
GcryDigestEntry *list;
- byte *macpads;
- int macpads_Bsize; /* Blocksize as used for the HMAC pads. */
};
@@ -331,43 +330,8 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
ctx->flags.secure = secure;
+ ctx->flags.hmac = hmac;
ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
-
- if (hmac)
- {
- switch (algo)
- {
- case GCRY_MD_SHA3_224:
- ctx->macpads_Bsize = 1152 / 8;
- break;
- case GCRY_MD_SHA3_256:
- ctx->macpads_Bsize = 1088 / 8;
- break;
- case GCRY_MD_SHA3_384:
- ctx->macpads_Bsize = 832 / 8;
- break;
- case GCRY_MD_SHA3_512:
- ctx->macpads_Bsize = 576 / 8;
- break;
- case GCRY_MD_SHA384:
- case GCRY_MD_SHA512:
- ctx->macpads_Bsize = 128;
- break;
- case GCRY_MD_GOSTR3411_94:
- case GCRY_MD_GOSTR3411_CP:
- ctx->macpads_Bsize = 32;
- break;
- default:
- ctx->macpads_Bsize = 64;
- break;
- }
- ctx->macpads = xtrymalloc_secure (2*(ctx->macpads_Bsize));
- if (!ctx->macpads)
- {
- err = gpg_err_code_from_errno (errno);
- md_close (hd);
- }
- }
}
if (! err)
@@ -447,7 +411,7 @@ md_enable (gcry_md_hd_t hd, int algorithm)
if (!err)
{
size_t size = (sizeof (*entry)
- + spec->contextsize
+ + spec->contextsize * (h->flags.hmac? 3 : 1)
- sizeof (entry->context));
/* And allocate a new list entry. */
@@ -515,17 +479,6 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
memcpy (b, a, sizeof *a);
b->list = NULL;
b->debug = NULL;
- if (a->macpads)
- {
- b->macpads = xtrymalloc_secure (2*(a->macpads_Bsize));
- if (! b->macpads)
- {
- err = gpg_err_code_from_errno (errno);
- md_close (bhd);
- }
- else
- memcpy (b->macpads, a->macpads, (2*(a->macpads_Bsize)));
- }
}
/* Copy the complete list of algorithms. The copied list is
@@ -535,13 +488,9 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
for (ar = a->list; ar; ar = ar->next)
{
if (a->flags.secure)
- br = xtrymalloc_secure (sizeof *br
- + ar->spec->contextsize
- - sizeof(ar->context));
+ br = xtrymalloc_secure (ar->actual_struct_size);
else
- br = xtrymalloc (sizeof *br
- + ar->spec->contextsize
- - sizeof (ar->context));
+ br = xtrymalloc (ar->actual_struct_size);
if (!br)
{
err = gpg_err_code_from_errno (errno);
@@ -549,8 +498,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
break;
}
- memcpy (br, ar, (sizeof (*br) + ar->spec->contextsize
- - sizeof (ar->context)));
+ memcpy (br, ar, ar->actual_struct_size);
br->next = b->list;
b->list = br;
}
@@ -591,14 +539,19 @@ _gcry_md_reset (gcry_md_hd_t a)
a->bufpos = a->ctx->flags.finalized = 0;
- for (r = a->ctx->list; r; r = r->next)
- {
- memset (r->context.c, 0, r->spec->contextsize);
- (*r->spec->init) (&r->context.c,
- a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
- }
- if (a->ctx->macpads)
- md_write (a, a->ctx->macpads, a->ctx->macpads_Bsize); /* inner pad */
+ if (a->ctx->flags.hmac)
+ for (r = a->ctx->list; r; r = r->next)
+ {
+ memcpy (r->context.c, r->context.c + r->spec->contextsize,
+ r->spec->contextsize);
+ }
+ else
+ for (r = a->ctx->list; r; r = r->next)
+ {
+ memset (r->context.c, 0, r->spec->contextsize);
+ (*r->spec->init) (&r->context.c,
+ a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
+ }
}
@@ -618,12 +571,6 @@ md_close (gcry_md_hd_t a)
xfree (r);
}
- if (a->ctx->macpads)
- {
- wipememory (a->ctx->macpads, 2*(a->ctx->macpads_Bsize));
- xfree(a->ctx->macpads);
- }
-
wipememory (a, a->ctx->actual_handle_size);
xfree(a);
}
@@ -686,66 +633,120 @@ md_final (gcry_md_hd_t a)
a->ctx->flags.finalized = 1;
- if (a->ctx->macpads)
+ if (!a->ctx->flags.hmac)
+ return;
+
+ for (r = a->ctx->list; r; r = r->next)
{
- /* Finish the hmac. */
- int algo = md_get_algo (a);
- byte *p = md_read (a, algo);
- size_t dlen = md_digest_length (algo);
- gcry_md_hd_t om;
+ byte *p = r->spec->read (&r->context.c);
+ size_t dlen = r->spec->mdlen;
+ byte *hash;
gcry_err_code_t err;
- err = md_open (&om, algo,
- ((a->ctx->flags.secure? GCRY_MD_FLAG_SECURE:0)
- | (a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0)));
- if (err)
- _gcry_fatal_error (err, NULL);
- md_write (om,
- (a->ctx->macpads)+(a->ctx->macpads_Bsize),
- a->ctx->macpads_Bsize);
- md_write (om, p, dlen);
- md_final (om);
- /* Replace our digest with the mac (they have the same size). */
- memcpy (p, md_read (om, algo), dlen);
- md_close (om);
+ if (a->ctx->flags.secure)
+ hash = xtrymalloc_secure (dlen);
+ else
+ hash = xtrymalloc (dlen);
+ if (!hash)
+ {
+ err = gpg_err_code_from_errno (errno);
+ _gcry_fatal_error (err, NULL);
+ }
+
+ memcpy (hash, p, dlen);
+ memcpy (r->context.c, r->context.c + r->spec->contextsize * 2,
+ r->spec->contextsize);
+ (*r->spec->write) (&r->context.c, hash, dlen);
+ (*r->spec->final) (&r->context.c);
+ xfree (hash);
}
}
static gcry_err_code_t
-prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen)
+prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
{
- int i;
- int algo = md_get_algo (hd);
- unsigned char *helpkey = NULL;
- unsigned char *ipad, *opad;
+ GcryDigestEntry *r;
- if (!algo)
+ if (!a->ctx->list)
return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */
- if ( keylen > hd->ctx->macpads_Bsize )
+ for (r = a->ctx->list; r; r = r->next)
{
- helpkey = xtrymalloc_secure (md_digest_length (algo));
- if (!helpkey)
- return gpg_err_code_from_errno (errno);
- _gcry_md_hash_buffer (algo, helpkey, key, keylen);
- key = helpkey;
- keylen = md_digest_length (algo);
- gcry_assert ( keylen <= hd->ctx->macpads_Bsize );
- }
+ const unsigned char *k;
+ size_t k_len;
+ unsigned char *key_allocated = NULL;
+ int macpad_Bsize;
+ int i;
- memset ( hd->ctx->macpads, 0, 2*(hd->ctx->macpads_Bsize) );
- ipad = hd->ctx->macpads;
- opad = (hd->ctx->macpads)+(hd->ctx->macpads_Bsize);
- memcpy ( ipad, key, keylen );
- memcpy ( opad, key, keylen );
- for (i=0; i < hd->ctx->macpads_Bsize; i++ )
- {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
+ switch (r->spec->algo)
+ {
+ case GCRY_MD_SHA3_224:
+ macpad_Bsize = 1152 / 8;
+ break;
+ case GCRY_MD_SHA3_256:
+ macpad_Bsize = 1088 / 8;
+ break;
+ case GCRY_MD_SHA3_384:
+ macpad_Bsize = 832 / 8;
+ break;
+ case GCRY_MD_SHA3_512:
+ macpad_Bsize = 576 / 8;
+ break;
+ case GCRY_MD_SHA384:
+ case GCRY_MD_SHA512:
+ macpad_Bsize = 128;
+ break;
+ case GCRY_MD_GOSTR3411_94:
+ case GCRY_MD_GOSTR3411_CP:
+ macpad_Bsize = 32;
+ break;
+ default:
+ macpad_Bsize = 64;
+ break;
+ }
+
+ if ( keylen > macpad_Bsize )
+ {
+ k = key_allocated = xtrymalloc_secure (r->spec->mdlen);
+ if (!k)
+ return gpg_err_code_from_errno (errno);
+ _gcry_md_hash_buffer (r->spec->algo, key_allocated, key, keylen);
+ k_len = r->spec->mdlen;
+ gcry_assert ( k_len <= macpad_Bsize );
+ }
+ else
+ {
+ k = key;
+ k_len = keylen;
+ }
+
+ (*r->spec->init) (&r->context.c,
+ a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
+ a->bufpos = 0;
+ for (i=0; i < k_len; i++ )
+ _gcry_md_putc (a, k[i] ^ 0x36);
+ for (; i < macpad_Bsize; i++ )
+ _gcry_md_putc (a, 0x36);
+ (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
+ memcpy (r->context.c + r->spec->contextsize, r->context.c,
+ r->spec->contextsize);
+
+ (*r->spec->init) (&r->context.c,
+ a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
+ a->bufpos = 0;
+ for (i=0; i < k_len; i++ )
+ _gcry_md_putc (a, k[i] ^ 0x5c);
+ for (; i < macpad_Bsize; i++ )
+ _gcry_md_putc (a, 0x5c);
+ (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
+ memcpy (r->context.c + r->spec->contextsize*2, r->context.c,
+ r->spec->contextsize);
+
+ xfree (key_allocated);
}
- xfree (helpkey);
+ a->bufpos = 0;
return 0;
}
@@ -780,14 +781,9 @@ _gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
{
gcry_err_code_t rc;
- if (!hd->ctx->macpads)
- rc = GPG_ERR_CONFLICT;
- else
- {
- rc = prepare_macpads (hd, key, keylen);
- if (!rc)
- _gcry_md_reset (hd);
- }
+ rc = prepare_macpads (hd, key, keylen);
+ if (!rc)
+ _gcry_md_reset (hd);
return rc;
}