1 /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms,
5  * with or without modification, are permitted provided
6  * that the following conditions are met:
7  *
8  *   Redistributions of source code must retain the above
9  *   copyright notice, this list of conditions and the
10  *   following disclaimer.
11  *
12  *   Redistributions in binary form must reproduce the above
13  *   copyright notice, this list of conditions and the following
14  *   disclaimer in the documentation and/or other materials
15  *   provided with the distribution.
16  *
17  *   Neither the name of the copyright holder nor the names
18  *   of any other contributors may be used to endorse or
19  *   promote products derived from this software without
20  *   specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  */
37 
38 #include "libssh2_priv.h"
39 #include "mac.h"
40 
41 #ifdef LIBSSH2_MAC_NONE
42 /* mac_none_MAC
43  * Minimalist MAC: No MAC
44  */
45 static int
mac_none_MAC(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)46 mac_none_MAC(LIBSSH2_SESSION * session, unsigned char *buf,
47              uint32_t seqno, const unsigned char *packet,
48              uint32_t packet_len, const unsigned char *addtl,
49              uint32_t addtl_len, void **abstract)
50 {
51     return 0;
52 }
53 
54 
55 
56 
57 static LIBSSH2_MAC_METHOD mac_method_none = {
58     "none",
59     0,
60     0,
61     NULL,
62     mac_none_MAC,
63     NULL
64 };
65 #endif /* LIBSSH2_MAC_NONE */
66 
67 /* mac_method_common_init
68  * Initialize simple mac methods
69  */
70 static int
mac_method_common_init(LIBSSH2_SESSION * session,unsigned char * key,int * free_key,void ** abstract)71 mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key,
72                        int *free_key, void **abstract)
73 {
74     *abstract = key;
75     *free_key = 0;
76     (void) session;
77 
78     return 0;
79 }
80 
81 
82 
83 /* mac_method_common_dtor
84  * Cleanup simple mac methods
85  */
86 static int
mac_method_common_dtor(LIBSSH2_SESSION * session,void ** abstract)87 mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract)
88 {
89     if (*abstract) {
90         LIBSSH2_FREE(session, *abstract);
91     }
92     *abstract = NULL;
93 
94     return 0;
95 }
96 
97 
98 
99 #if LIBSSH2_HMAC_SHA512
100 /* mac_method_hmac_sha512_hash
101  * Calculate hash using full sha512 value
102  */
103 static int
mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)104 mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session,
105                           unsigned char *buf, uint32_t seqno,
106                           const unsigned char *packet,
107                           uint32_t packet_len,
108                           const unsigned char *addtl,
109                           uint32_t addtl_len, void **abstract)
110 {
111     libssh2_hmac_ctx ctx;
112     unsigned char seqno_buf[4];
113     (void) session;
114 
115     _libssh2_htonu32(seqno_buf, seqno);
116 
117     libssh2_hmac_ctx_init(ctx);
118     libssh2_hmac_sha512_init(&ctx, *abstract, 64);
119     libssh2_hmac_update(ctx, seqno_buf, 4);
120     libssh2_hmac_update(ctx, packet, packet_len);
121     if (addtl && addtl_len) {
122         libssh2_hmac_update(ctx, addtl, addtl_len);
123     }
124     libssh2_hmac_final(ctx, buf);
125     libssh2_hmac_cleanup(&ctx);
126 
127     return 0;
128 }
129 
130 
131 
132 static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_512 = {
133     "hmac-sha2-512",
134     64,
135     64,
136     mac_method_common_init,
137     mac_method_hmac_sha2_512_hash,
138     mac_method_common_dtor,
139 };
140 #endif
141 
142 
143 
144 #if LIBSSH2_HMAC_SHA256
145 /* mac_method_hmac_sha256_hash
146  * Calculate hash using full sha256 value
147  */
148 static int
mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)149 mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session,
150                           unsigned char *buf, uint32_t seqno,
151                           const unsigned char *packet,
152                           uint32_t packet_len,
153                           const unsigned char *addtl,
154                           uint32_t addtl_len, void **abstract)
155 {
156     libssh2_hmac_ctx ctx;
157     unsigned char seqno_buf[4];
158     (void) session;
159 
160     _libssh2_htonu32(seqno_buf, seqno);
161 
162     libssh2_hmac_ctx_init(ctx);
163     libssh2_hmac_sha256_init(&ctx, *abstract, 32);
164     libssh2_hmac_update(ctx, seqno_buf, 4);
165     libssh2_hmac_update(ctx, packet, packet_len);
166     if (addtl && addtl_len) {
167         libssh2_hmac_update(ctx, addtl, addtl_len);
168     }
169     libssh2_hmac_final(ctx, buf);
170     libssh2_hmac_cleanup(&ctx);
171 
172     return 0;
173 }
174 
175 
176 
177 static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_256 = {
178     "hmac-sha2-256",
179     32,
180     32,
181     mac_method_common_init,
182     mac_method_hmac_sha2_256_hash,
183     mac_method_common_dtor,
184 };
185 #endif
186 
187 
188 
189 
190 /* mac_method_hmac_sha1_hash
191  * Calculate hash using full sha1 value
192  */
193 static int
mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)194 mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session,
195                           unsigned char *buf, uint32_t seqno,
196                           const unsigned char *packet,
197                           uint32_t packet_len,
198                           const unsigned char *addtl,
199                           uint32_t addtl_len, void **abstract)
200 {
201     libssh2_hmac_ctx ctx;
202     unsigned char seqno_buf[4];
203     (void) session;
204 
205     _libssh2_htonu32(seqno_buf, seqno);
206 
207     libssh2_hmac_ctx_init(ctx);
208     libssh2_hmac_sha1_init(&ctx, *abstract, 20);
209     libssh2_hmac_update(ctx, seqno_buf, 4);
210     libssh2_hmac_update(ctx, packet, packet_len);
211     if (addtl && addtl_len) {
212         libssh2_hmac_update(ctx, addtl, addtl_len);
213     }
214     libssh2_hmac_final(ctx, buf);
215     libssh2_hmac_cleanup(&ctx);
216 
217     return 0;
218 }
219 
220 
221 
222 static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1 = {
223     "hmac-sha1",
224     20,
225     20,
226     mac_method_common_init,
227     mac_method_hmac_sha1_hash,
228     mac_method_common_dtor,
229 };
230 
231 /* mac_method_hmac_sha1_96_hash
232  * Calculate hash using first 96 bits of sha1 value
233  */
234 static int
mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)235 mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session,
236                              unsigned char *buf, uint32_t seqno,
237                              const unsigned char *packet,
238                              uint32_t packet_len,
239                              const unsigned char *addtl,
240                              uint32_t addtl_len, void **abstract)
241 {
242     unsigned char temp[SHA_DIGEST_LENGTH];
243 
244     mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len,
245                               addtl, addtl_len, abstract);
246     memcpy(buf, (char *) temp, 96 / 8);
247 
248     return 0;
249 }
250 
251 
252 
253 static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1_96 = {
254     "hmac-sha1-96",
255     12,
256     20,
257     mac_method_common_init,
258     mac_method_hmac_sha1_96_hash,
259     mac_method_common_dtor,
260 };
261 
262 #if LIBSSH2_MD5
263 /* mac_method_hmac_md5_hash
264  * Calculate hash using full md5 value
265  */
266 static int
mac_method_hmac_md5_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)267 mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf,
268                          uint32_t seqno,
269                          const unsigned char *packet,
270                          uint32_t packet_len,
271                          const unsigned char *addtl,
272                          uint32_t addtl_len, void **abstract)
273 {
274     libssh2_hmac_ctx ctx;
275     unsigned char seqno_buf[4];
276     (void) session;
277 
278     _libssh2_htonu32(seqno_buf, seqno);
279 
280     libssh2_hmac_ctx_init(ctx);
281     libssh2_hmac_md5_init(&ctx, *abstract, 16);
282     libssh2_hmac_update(ctx, seqno_buf, 4);
283     libssh2_hmac_update(ctx, packet, packet_len);
284     if (addtl && addtl_len) {
285         libssh2_hmac_update(ctx, addtl, addtl_len);
286     }
287     libssh2_hmac_final(ctx, buf);
288     libssh2_hmac_cleanup(&ctx);
289 
290     return 0;
291 }
292 
293 
294 
295 static const LIBSSH2_MAC_METHOD mac_method_hmac_md5 = {
296     "hmac-md5",
297     16,
298     16,
299     mac_method_common_init,
300     mac_method_hmac_md5_hash,
301     mac_method_common_dtor,
302 };
303 
304 /* mac_method_hmac_md5_96_hash
305  * Calculate hash using first 96 bits of md5 value
306  */
307 static int
mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)308 mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session,
309                             unsigned char *buf, uint32_t seqno,
310                             const unsigned char *packet,
311                             uint32_t packet_len,
312                             const unsigned char *addtl,
313                             uint32_t addtl_len, void **abstract)
314 {
315     unsigned char temp[MD5_DIGEST_LENGTH];
316     mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len,
317                              addtl, addtl_len, abstract);
318     memcpy(buf, (char *) temp, 96 / 8);
319     return 0;
320 }
321 
322 
323 
324 static const LIBSSH2_MAC_METHOD mac_method_hmac_md5_96 = {
325     "hmac-md5-96",
326     12,
327     16,
328     mac_method_common_init,
329     mac_method_hmac_md5_96_hash,
330     mac_method_common_dtor,
331 };
332 #endif /* LIBSSH2_MD5 */
333 
334 #if LIBSSH2_HMAC_RIPEMD
335 /* mac_method_hmac_ripemd160_hash
336  * Calculate hash using ripemd160 value
337  */
338 static int
mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session,unsigned char * buf,uint32_t seqno,const unsigned char * packet,uint32_t packet_len,const unsigned char * addtl,uint32_t addtl_len,void ** abstract)339 mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session,
340                                unsigned char *buf, uint32_t seqno,
341                                const unsigned char *packet,
342                                uint32_t packet_len,
343                                const unsigned char *addtl,
344                                uint32_t addtl_len,
345                                void **abstract)
346 {
347     libssh2_hmac_ctx ctx;
348     unsigned char seqno_buf[4];
349     (void) session;
350 
351     _libssh2_htonu32(seqno_buf, seqno);
352 
353     libssh2_hmac_ctx_init(ctx);
354     libssh2_hmac_ripemd160_init(&ctx, *abstract, 20);
355     libssh2_hmac_update(ctx, seqno_buf, 4);
356     libssh2_hmac_update(ctx, packet, packet_len);
357     if (addtl && addtl_len) {
358         libssh2_hmac_update(ctx, addtl, addtl_len);
359     }
360     libssh2_hmac_final(ctx, buf);
361     libssh2_hmac_cleanup(&ctx);
362 
363     return 0;
364 }
365 
366 
367 
368 static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160 = {
369     "hmac-ripemd160",
370     20,
371     20,
372     mac_method_common_init,
373     mac_method_hmac_ripemd160_hash,
374     mac_method_common_dtor,
375 };
376 
377 static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160_openssh_com = {
378     "hmac-ripemd160@openssh.com",
379     20,
380     20,
381     mac_method_common_init,
382     mac_method_hmac_ripemd160_hash,
383     mac_method_common_dtor,
384 };
385 #endif /* LIBSSH2_HMAC_RIPEMD */
386 
387 static const LIBSSH2_MAC_METHOD *mac_methods[] = {
388 #if LIBSSH2_HMAC_SHA256
389     &mac_method_hmac_sha2_256,
390 #endif
391 #if LIBSSH2_HMAC_SHA512
392     &mac_method_hmac_sha2_512,
393 #endif
394     &mac_method_hmac_sha1,
395     &mac_method_hmac_sha1_96,
396 #if LIBSSH2_MD5
397     &mac_method_hmac_md5,
398     &mac_method_hmac_md5_96,
399 #endif
400 #if LIBSSH2_HMAC_RIPEMD
401     &mac_method_hmac_ripemd160,
402     &mac_method_hmac_ripemd160_openssh_com,
403 #endif /* LIBSSH2_HMAC_RIPEMD */
404 #ifdef LIBSSH2_MAC_NONE
405     &mac_method_none,
406 #endif /* LIBSSH2_MAC_NONE */
407     NULL
408 };
409 
410 const LIBSSH2_MAC_METHOD **
_libssh2_mac_methods(void)411 _libssh2_mac_methods(void)
412 {
413     return mac_methods;
414 }
415