1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
// Copyright (C) 2010-2014 David Sugar, Tycho Softworks.
// Copyright (C) 2015-2020 Cherokees of Idaho.
//
// This file is part of GNU uCommon C++.
//
// GNU uCommon C++ is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU uCommon C++ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
#include "local.h"
// for older/broken versions of gnutls_hmac_init headers
namespace ucommon {
class __LOCAL __multicode
{
public:
int code;
inline operator HMAC_ID()
{return (HMAC_ID)code;}
inline operator MD_ID()
{return (MD_ID)code;}
};
void HMAC::release(void)
{
if(context) {
gnutls_hmac_deinit((HMAC_CTX)context, buffer);
context = NULL;
}
bufsize = 0;
textbuf[0] = 0;
hmacid = 0;
}
int __context::map_hmac(const char *type)
{
if(eq_case(type, "sha") || eq_case(type, "sha1") || eq_case(type, "sha160"))
return GNUTLS_MAC_SHA1;
else if(eq_case(type, "sha256"))
return GNUTLS_MAC_SHA256;
else if(eq_case(type, "sha224"))
return GNUTLS_MAC_SHA224;
else if(eq_case(type, "sha384"))
return GNUTLS_MAC_SHA384;
else if(eq_case(type, "sha512"))
return GNUTLS_MAC_SHA512;
else if(eq_case(type, "md5"))
return GNUTLS_MAC_MD5;
else if(eq_case(type, "md2"))
return GNUTLS_MAC_MD2;
else if(eq_case(type, "rmd160"))
return GNUTLS_MAC_RMD160;
else
return 0;
}
void HMAC::set(const char *digest, const secure::keybytes& key)
{
secure::init();
release();
size_t len = key.size() / 8;
if(!len)
return;
hmacid = __context::map_hmac(digest);
__multicode id;
id.code = hmacid;
if(hmacid)
gnutls_hmac_init((HMAC_CTX *)&context, id, *key, len);
}
bool HMAC::has(const char *type)
{
HMAC_ID id = (HMAC_ID)__context::map_hmac(type);
if(!id || (gnutls_hmac_get_len(id) < 1))
return false;
return true;
}
bool HMAC::put(const void *address, size_t size)
{
if(!context || hmacid == 0)
return false;
gnutls_hmac((HMAC_CTX)context, address, size);
return true;
}
const uint8_t *HMAC::get(void)
{
unsigned count = 0;
unsigned size = 0;
if(bufsize)
return buffer;
if(!context || hmacid == 0)
return NULL;
size = gnutls_hmac_get_len((HMAC_ID)hmacid);
release();
bufsize = size;
while(count < bufsize) {
snprintf(textbuf + (count * 2), 3, "%2.2x",
buffer[count]);
++count;
}
return buffer;
}
} // namespace ucommon
|