diff options
Diffstat (limited to 'contrib/pgcrypto/px-hmac.c')
-rw-r--r-- | contrib/pgcrypto/px-hmac.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/contrib/pgcrypto/px-hmac.c b/contrib/pgcrypto/px-hmac.c new file mode 100644 index 0000000..99174d2 --- /dev/null +++ b/contrib/pgcrypto/px-hmac.c @@ -0,0 +1,176 @@ +/* + * px-hmac.c + * HMAC implementation. + * + * Copyright (c) 2001 Marko Kreen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * contrib/pgcrypto/px-hmac.c + */ + +#include "postgres.h" + +#include "px.h" + +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5C + +static unsigned +hmac_result_size(PX_HMAC *h) +{ + return px_md_result_size(h->md); +} + +static unsigned +hmac_block_size(PX_HMAC *h) +{ + return px_md_block_size(h->md); +} + +static void +hmac_init(PX_HMAC *h, const uint8 *key, unsigned klen) +{ + unsigned bs, + i; + uint8 *keybuf; + PX_MD *md = h->md; + + bs = px_md_block_size(md); + keybuf = palloc0(bs); + + if (klen > bs) + { + px_md_update(md, key, klen); + px_md_finish(md, keybuf); + px_md_reset(md); + } + else + memcpy(keybuf, key, klen); + + for (i = 0; i < bs; i++) + { + h->p.ipad[i] = keybuf[i] ^ HMAC_IPAD; + h->p.opad[i] = keybuf[i] ^ HMAC_OPAD; + } + + px_memset(keybuf, 0, bs); + pfree(keybuf); + + px_md_update(md, h->p.ipad, bs); +} + +static void +hmac_reset(PX_HMAC *h) +{ + PX_MD *md = h->md; + unsigned bs = px_md_block_size(md); + + px_md_reset(md); + px_md_update(md, h->p.ipad, bs); +} + +static void +hmac_update(PX_HMAC *h, const uint8 *data, unsigned dlen) +{ + px_md_update(h->md, data, dlen); +} + +static void +hmac_finish(PX_HMAC *h, uint8 *dst) +{ + PX_MD *md = h->md; + unsigned bs, + hlen; + uint8 *buf; + + bs = px_md_block_size(md); + hlen = px_md_result_size(md); + + buf = palloc(hlen); + + px_md_finish(md, buf); + + px_md_reset(md); + px_md_update(md, h->p.opad, bs); + px_md_update(md, buf, hlen); + px_md_finish(md, dst); + + px_memset(buf, 0, hlen); + pfree(buf); +} + +static void +hmac_free(PX_HMAC *h) +{ + unsigned bs; + + bs = px_md_block_size(h->md); + px_md_free(h->md); + + px_memset(h->p.ipad, 0, bs); + px_memset(h->p.opad, 0, bs); + pfree(h->p.ipad); + pfree(h->p.opad); + pfree(h); +} + + +/* PUBLIC FUNCTIONS */ + +int +px_find_hmac(const char *name, PX_HMAC **res) +{ + int err; + PX_MD *md; + PX_HMAC *h; + unsigned bs; + + err = px_find_digest(name, &md); + if (err) + return err; + + bs = px_md_block_size(md); + if (bs < 2) + { + px_md_free(md); + return PXE_HASH_UNUSABLE_FOR_HMAC; + } + + h = palloc(sizeof(*h)); + h->p.ipad = palloc(bs); + h->p.opad = palloc(bs); + h->md = md; + + h->result_size = hmac_result_size; + h->block_size = hmac_block_size; + h->reset = hmac_reset; + h->update = hmac_update; + h->finish = hmac_finish; + h->free = hmac_free; + h->init = hmac_init; + + *res = h; + + return 0; +} |