Header And Logo

PostgreSQL
| The world's most advanced open source database.

px-hmac.c

Go to the documentation of this file.
00001 /*
00002  * px-hmac.c
00003  *      HMAC implementation.
00004  *
00005  * Copyright (c) 2001 Marko Kreen
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * contrib/pgcrypto/px-hmac.c
00030  */
00031 
00032 #include "postgres.h"
00033 
00034 #include "px.h"
00035 
00036 #define HMAC_IPAD 0x36
00037 #define HMAC_OPAD 0x5C
00038 
00039 static unsigned
00040 hmac_result_size(PX_HMAC *h)
00041 {
00042     return px_md_result_size(h->md);
00043 }
00044 
00045 static unsigned
00046 hmac_block_size(PX_HMAC *h)
00047 {
00048     return px_md_block_size(h->md);
00049 }
00050 
00051 static void
00052 hmac_init(PX_HMAC *h, const uint8 *key, unsigned klen)
00053 {
00054     unsigned    bs,
00055                 i;
00056     uint8      *keybuf;
00057     PX_MD      *md = h->md;
00058 
00059     bs = px_md_block_size(md);
00060     keybuf = px_alloc(bs);
00061     memset(keybuf, 0, bs);
00062 
00063     if (klen > bs)
00064     {
00065         px_md_update(md, key, klen);
00066         px_md_finish(md, keybuf);
00067         px_md_reset(md);
00068     }
00069     else
00070         memcpy(keybuf, key, klen);
00071 
00072     for (i = 0; i < bs; i++)
00073     {
00074         h->p.ipad[i] = keybuf[i] ^ HMAC_IPAD;
00075         h->p.opad[i] = keybuf[i] ^ HMAC_OPAD;
00076     }
00077 
00078     memset(keybuf, 0, bs);
00079     px_free(keybuf);
00080 
00081     px_md_update(md, h->p.ipad, bs);
00082 }
00083 
00084 static void
00085 hmac_reset(PX_HMAC *h)
00086 {
00087     PX_MD      *md = h->md;
00088     unsigned    bs = px_md_block_size(md);
00089 
00090     px_md_reset(md);
00091     px_md_update(md, h->p.ipad, bs);
00092 }
00093 
00094 static void
00095 hmac_update(PX_HMAC *h, const uint8 *data, unsigned dlen)
00096 {
00097     px_md_update(h->md, data, dlen);
00098 }
00099 
00100 static void
00101 hmac_finish(PX_HMAC *h, uint8 *dst)
00102 {
00103     PX_MD      *md = h->md;
00104     unsigned    bs,
00105                 hlen;
00106     uint8      *buf;
00107 
00108     bs = px_md_block_size(md);
00109     hlen = px_md_result_size(md);
00110 
00111     buf = px_alloc(hlen);
00112 
00113     px_md_finish(md, buf);
00114 
00115     px_md_reset(md);
00116     px_md_update(md, h->p.opad, bs);
00117     px_md_update(md, buf, hlen);
00118     px_md_finish(md, dst);
00119 
00120     memset(buf, 0, hlen);
00121     px_free(buf);
00122 }
00123 
00124 static void
00125 hmac_free(PX_HMAC *h)
00126 {
00127     unsigned    bs;
00128 
00129     bs = px_md_block_size(h->md);
00130     px_md_free(h->md);
00131 
00132     memset(h->p.ipad, 0, bs);
00133     memset(h->p.opad, 0, bs);
00134     px_free(h->p.ipad);
00135     px_free(h->p.opad);
00136     px_free(h);
00137 }
00138 
00139 
00140 /* PUBLIC FUNCTIONS */
00141 
00142 int
00143 px_find_hmac(const char *name, PX_HMAC **res)
00144 {
00145     int         err;
00146     PX_MD      *md;
00147     PX_HMAC    *h;
00148     unsigned    bs;
00149 
00150     err = px_find_digest(name, &md);
00151     if (err)
00152         return err;
00153 
00154     bs = px_md_block_size(md);
00155     if (bs < 2)
00156     {
00157         px_md_free(md);
00158         return PXE_HASH_UNUSABLE_FOR_HMAC;
00159     }
00160 
00161     h = px_alloc(sizeof(*h));
00162     h->p.ipad = px_alloc(bs);
00163     h->p.opad = px_alloc(bs);
00164     h->md = md;
00165 
00166     h->result_size = hmac_result_size;
00167     h->block_size = hmac_block_size;
00168     h->reset = hmac_reset;
00169     h->update = hmac_update;
00170     h->finish = hmac_finish;
00171     h->free = hmac_free;
00172     h->init = hmac_init;
00173 
00174     *res = h;
00175 
00176     return 0;
00177 }