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