1 /* Portions of this file are subject to the following copyright(s).  See
2  * the Net-SNMP's COPYING file for more details and other copyrights
3  * that may apply:
4  */
5 /*
6  * Portions of this file are copyrighted by:
7  * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
8  * Use is subject to license terms specified in the COPYING file
9  * distributed with the Net-SNMP package.
10  *
11  * Portions of this file are copyrighted by:
12  * Copyright (c) 2016 VMware, Inc. All rights reserved.
13  * Use is subject to license terms specified in the COPYING file
14  * distributed with the Net-SNMP package.
15  */
16 
17 /*
18  * scapi.c
19  *
20  */
21 
22 #include <net-snmp/net-snmp-config.h>
23 #include <net-snmp/net-snmp-features.h>
24 
25 #ifdef HAVE_INTTYPES_H
26 #include <inttypes.h>
27 #endif
28 #include <sys/types.h>
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #if HAVE_STRING_H
33 #include <string.h>
34 #else
35 #include <strings.h>
36 #endif
37 #if TIME_WITH_SYS_TIME
38 # include <sys/time.h>
39 # include <time.h>
40 #else
41 # if HAVE_SYS_TIME_H
42 #  include <sys/time.h>
43 # else
44 #  include <time.h>
45 # endif
46 #endif
47 #ifdef HAVE_NETINET_IN_H
48 #include <netinet/in.h>
49 #endif
50 
51 #if HAVE_UNISTD_H
52 #include <unistd.h>
53 #endif
54 #include "memcheck.h"
55 
56 #include <net-snmp/types.h>
57 #include <net-snmp/output_api.h>
58 #include <net-snmp/utilities.h>
59 
60 netsnmp_feature_child_of(usm_support, libnetsnmp);
61 netsnmp_feature_child_of(usm_scapi, usm_support);
62 
63 #ifndef NETSNMP_FEATURE_REMOVE_USM_SCAPI
64 
65 #ifdef NETSNMP_USE_INTERNAL_MD5
66 #include <net-snmp/library/md5.h>
67 #endif
68 #include <net-snmp/library/snmp_api.h>
69 #include <net-snmp/library/callback.h>
70 #include <net-snmp/library/snmp_secmod.h>
71 #include <net-snmp/library/snmpusm.h>
72 #include <net-snmp/library/keytools.h>
73 #include <net-snmp/library/scapi.h>
74 #include <net-snmp/library/mib.h>
75 #include <net-snmp/library/transform_oids.h>
76 
77 #ifdef NETSNMP_USE_INTERNAL_CRYPTO
78 #include <net-snmp/library/openssl_md5.h>
79 #include <net-snmp/library/openssl_sha.h>
80 #include <net-snmp/library/openssl_des.h>
81 #include <net-snmp/library/openssl_aes.h>
82 #endif
83 
84 #ifdef NETSNMP_USE_OPENSSL
85 #include <openssl/hmac.h>
86 #include <openssl/evp.h>
87 #include <openssl/rand.h>
88 #include <openssl/des.h>
89 #ifdef HAVE_AES
90 #include <openssl/aes.h>
91 #endif
92 
93 #ifndef NETSNMP_DISABLE_DES
94 #ifdef HAVE_STRUCT_DES_KS_STRUCT_WEAK_KEY
95 /* these are older names for newer structures that exist in openssl .9.7 */
96 #define DES_key_schedule    des_key_schedule
97 #define DES_cblock          des_cblock
98 #define DES_key_sched       des_key_sched
99 #define DES_ncbc_encrypt    des_ncbc_encrypt
100 #define DES_cbc_encrypt    des_cbc_encrypt
101 #define OLD_DES
102 #endif
103 #endif
104 
105 #endif /* HAVE_OPENSSL */
106 
107 #ifdef NETSNMP_USE_INTERNAL_CRYPTO
108 #endif
109 
110 #ifdef NETSNMP_USE_PKCS11
111 #include <security/cryptoki.h>
112 #endif
113 
114 #ifdef QUITFUN
115 #undef QUITFUN
116 #define QUITFUN(e, l) do {                              \
117 	if (e != SNMPERR_SUCCESS) {			\
118 		rval = SNMPERR_SC_GENERAL_FAILURE;	\
119 		goto l ;				\
120         }                                               \
121     } while (0)
122 #endif
123 
124 #ifdef NETSNMP_USE_INTERNAL_CRYPTO
125 static
126 int SHA1_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
127               const u_char * secret, size_t secretlen);
128 
129 static
130 int MD5_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
131              const u_char * secret, size_t secretlen);
132 #endif
133 
134 static netsnmp_auth_alg_info _auth_alg_info[] = {
135     { NETSNMP_USMAUTH_NOAUTH, "usmNoAuthProtocol", usmNoAuthProtocol,
136       OID_LENGTH(usmNoAuthProtocol), 0, 0 },
137     { NETSNMP_USMAUTH_HMACSHA1, "usmHMACSHA1AuthProtocol",
138       usmHMACSHA1AuthProtocol, OID_LENGTH(usmHMACSHA1AuthProtocol),
139       BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1), USM_MD5_AND_SHA_AUTH_LEN },
140 #ifndef NETSNMP_DISABLE_MD5
141     { NETSNMP_USMAUTH_HMACMD5, "usmHMACMD5AuthProtocol",
142       usmHMACMD5AuthProtocol, OID_LENGTH(usmHMACMD5AuthProtocol),
143       BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5), USM_MD5_AND_SHA_AUTH_LEN },
144 #endif
145 #ifdef HAVE_EVP_SHA224
146     { NETSNMP_USMAUTH_HMAC128SHA224, "usmHMAC128SHA224AuthProtocol",
147       usmHMAC128SHA224AuthProtocol, OID_LENGTH(usmHMAC128SHA224AuthProtocol),
148       BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC128SHA224), USM_HMAC128SHA224_AUTH_LEN },
149     { NETSNMP_USMAUTH_HMAC192SHA256, "usmHMAC192SHA256AuthProtocol",
150       usmHMAC192SHA256AuthProtocol, OID_LENGTH(usmHMAC192SHA256AuthProtocol),
151       BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC192SHA256), USM_HMAC192SHA256_AUTH_LEN },
152 #endif
153 #ifdef HAVE_EVP_SHA384
154     { NETSNMP_USMAUTH_HMAC256SHA384, "usmHMAC256SHA384AuthProtocol",
155       usmHMAC256SHA384AuthProtocol, OID_LENGTH(usmHMAC256SHA384AuthProtocol),
156       BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC256SHA384), USM_HMAC256SHA384_AUTH_LEN },
157     { NETSNMP_USMAUTH_HMAC384SHA512, "usmHMAC384SHA512AuthProtocol",
158       usmHMAC384SHA512AuthProtocol, OID_LENGTH(usmHMAC384SHA512AuthProtocol),
159       BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC384SHA512), USM_HMAC384SHA512_AUTH_LEN },
160 #endif
161     { -1, "unknown", NULL, 0, 0, 0 }
162 };
163 
164 static netsnmp_priv_alg_info _priv_alg_info[] = {
165     { USM_CREATE_USER_PRIV_NONE, "usmNoPrivProtocol",
166       usmNoPrivProtocol, OID_LENGTH(usmNoPrivProtocol), 0, 0, 0 },
167 #ifndef NETSNMP_DISABLE_DES
168     { USM_CREATE_USER_PRIV_DES, "usmDESPrivProtocol",
169       usmDESPrivProtocol, OID_LENGTH(usmDESPrivProtocol),
170       BYTESIZE(SNMP_TRANS_PRIVLEN_1DES),
171       BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV),
172       BYTESIZE(SNMP_TRANS_PRIVLEN_1DES) },
173 #endif
174 #ifdef HAVE_AES
175     { USM_CREATE_USER_PRIV_AES, "usmAESPrivProtocol",
176       usmAESPrivProtocol, OID_LENGTH(usmAESPrivProtocol),
177       BYTESIZE(SNMP_TRANS_PRIVLEN_AES),
178       BYTESIZE(SNMP_TRANS_PRIVLEN_AES_IV),
179       0 },
180 #ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
181     { USM_CREATE_USER_PRIV_AES192, "usmAES192PrivProtocol",
182       usmAES192PrivProtocol, OID_LENGTH(usmAES192PrivProtocol),
183       BYTESIZE(SNMP_TRANS_PRIVLEN_AES192),
184       BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV),
185       0 },
186     { USM_CREATE_USER_PRIV_AES192_CISCO, "usmAES192CiscoPrivProtocol",
187       usmAES192CiscoPrivProtocol, OID_LENGTH(usmAES192CiscoPrivProtocol),
188       BYTESIZE(SNMP_TRANS_PRIVLEN_AES192),
189       BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV),
190       0 },
191     { USM_CREATE_USER_PRIV_AES256, "usmAES256PrivProtocol",
192       usmAES256PrivProtocol, OID_LENGTH(usmAES256PrivProtocol),
193       BYTESIZE(SNMP_TRANS_PRIVLEN_AES256),
194       BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV),
195       0 },
196     { USM_CREATE_USER_PRIV_AES256_CISCO, "usmAES256CiscoPrivProtocol",
197       usmAES256CiscoPrivProtocol, OID_LENGTH(usmAES256CiscoPrivProtocol),
198       BYTESIZE(SNMP_TRANS_PRIVLEN_AES256),
199       BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV),
200       0 },
201 #endif
202 #endif
203     { -1, NULL, NULL, 0 , 0, 0, 0 },
204 };
205 
206 
207 /*
208  * sc_get_priv_alg(oid *privoid, u_int len)
209  *
210  * returns a pointer to a netsnmp_priv_alg_info struct
211  */
212 netsnmp_priv_alg_info *
sc_get_priv_alg_byoid(const oid * privoid,u_int len)213 sc_get_priv_alg_byoid(const oid *privoid, u_int len)
214 {
215     int i = 0;
216 
217     DEBUGTRACE;
218 
219     if ((NULL == privoid) || (0 == len))
220         return NULL;
221 
222     for( ; _priv_alg_info[i].type != -1; ++i) {
223         if (len != _priv_alg_info[i].oid_len)
224             continue;
225         if (snmp_oid_compare(_priv_alg_info[i].alg_oid,
226                              _priv_alg_info[i].oid_len,
227                              privoid, len) == 0 )
228             return(&_priv_alg_info[i]);
229     }
230 
231     DEBUGMSGTL(("scapi", "no match for OID "));
232     DEBUGMSGOID(("scapi", privoid, len));
233     DEBUGMSG(("scapi", "\n"));
234     return NULL;
235 }
236 
237 /*
238  * sc_get_priv_alg_bytype(u_int type)
239  *
240  * returns a pointer to a netsnmp_priv_alg_info struct
241  */
242 netsnmp_priv_alg_info *
sc_get_priv_alg_bytype(u_int type)243 sc_get_priv_alg_bytype(u_int type)
244 {
245     int i = 0;
246 
247     DEBUGTRACE;
248 
249     for( ; _priv_alg_info[i].type != -1; ++i) {
250         if (type != _priv_alg_info[i].type)
251             continue;
252         return(&_priv_alg_info[i]);
253     }
254 
255     return NULL;
256 }
257 
258 /*
259  * sc_find_auth_alg(oid *authoid, u_int len)
260  *
261  * returns a pointer to a netsnmp_auth_alg_info struct
262  */
263 netsnmp_auth_alg_info *
sc_find_auth_alg_byoid(const oid * authoid,u_int len)264 sc_find_auth_alg_byoid(const oid *authoid, u_int len)
265 {
266     int i = 0;
267 
268     DEBUGTRACE;
269 
270     if ((NULL == authoid) || (0 == len))
271         return NULL;
272 
273     for( ; _auth_alg_info[i].type != -1; ++i) {
274         if (len != _auth_alg_info[i].oid_len)
275             continue;
276         if (snmp_oid_compare(_auth_alg_info[i].alg_oid,
277                              _auth_alg_info[i].oid_len,
278                              authoid, len) == 0 )
279             return(&_auth_alg_info[i]);
280     }
281 
282 /*    DEBUGMSGTL(("scapi", "No auth alg found for"));
283       DEBUGMSGOID(("scapi", authoid, len ));*/
284 
285     return NULL;
286 }
287 
288 /*
289  * sc_get_auth_alg_byindex(u_int index)
290  *
291  * returns a pointer to a netsnmp_auth_alg_info struct
292  */
293 netsnmp_auth_alg_info *
sc_get_auth_alg_byindex(u_int index)294 sc_get_auth_alg_byindex(u_int index)
295 {
296     DEBUGTRACE;
297 
298     if (index >= (sizeof(_auth_alg_info)) / (sizeof(_auth_alg_info[0])) ||
299         -1 == _auth_alg_info[index].type)
300         return NULL;
301 
302     return(&_auth_alg_info[index]);
303 }
304 
305 /*
306  * sc_find_auth_alg_bytype(u_int type)
307  *
308  * returns a pointer to a netsnmp_auth_alg_info struct
309  */
310 netsnmp_auth_alg_info *
sc_find_auth_alg_bytype(u_int type)311 sc_find_auth_alg_bytype(u_int type)
312 {
313     int i = 0;
314 
315     DEBUGTRACE;
316 
317     for( ; _auth_alg_info[i].type != -1; ++i) {
318         if (type != _auth_alg_info[i].type)
319             continue;
320         return(&_auth_alg_info[i]);
321     }
322 
323     return NULL;
324 }
325 
326 /*
327  * sc_get_authtype(oid *hashtype, u_int hashtype_len):
328  *
329  * Given a hashing type ("hashtype" and its length hashtype_len), return
330  * its type (the last suboid). NETSNMP_USMAUTH_* constants are defined in
331  * transform_oids.h.
332  *
333  * Returns SNMPERR_GENERR for an unknown hashing type.
334  */
335 int
sc_get_authtype(const oid * hashtype,u_int hashtype_len)336 sc_get_authtype(const oid * hashtype, u_int hashtype_len)
337 {
338     netsnmp_auth_alg_info *aai;
339 
340     DEBUGTRACE;
341 
342     aai = sc_find_auth_alg_byoid(hashtype, hashtype_len);
343     if (NULL == aai)
344         return SNMPERR_GENERR;
345 
346     return aai->type;
347 }
348 
349 int
sc_get_privtype(const oid * privtype,u_int privtype_len)350 sc_get_privtype(const oid * privtype, u_int privtype_len)
351 {
352     netsnmp_priv_alg_info *pai;
353 
354     DEBUGTRACE;
355 
356     pai = sc_get_priv_alg_byoid(privtype, privtype_len);
357     if (NULL == pai)
358         return SNMPERR_GENERR;
359 
360     return pai->type;
361 }
362 
363 /*
364  * sc_get_auth_maclen(int hashtype):
365  *
366  * Given a hash type, return its MAC length, which may be shorter than
367  * the full hash length.
368  *
369  * Returns 0 for an unknown hash type.
370  */
371 int
sc_get_auth_maclen(int hashtype)372 sc_get_auth_maclen(int hashtype)
373 {
374     netsnmp_auth_alg_info *aai;
375 
376     DEBUGTRACE;
377 
378     aai = sc_find_auth_alg_bytype(hashtype);
379     if (NULL == aai)
380         return 0;
381 
382     return aai->mac_length;
383 }
384 
385 /*
386  * sc_get_proper_auth_length_bytype(int hashtype):
387  *
388  * Given a hashing type, return the length of the hash result.
389  *
390  * Returns either the length or SNMPERR_GENERR for an unknown hashing type.
391  */
392 int
sc_get_proper_auth_length_bytype(int hashtype)393 sc_get_proper_auth_length_bytype(int hashtype)
394 {
395     netsnmp_auth_alg_info *aai;
396 
397     DEBUGTRACE;
398 
399     aai = sc_find_auth_alg_bytype(hashtype);
400     if (NULL == aai)
401         return SNMPERR_GENERR;
402 
403     return aai->proper_length;
404 }
405 
406 /*
407  * sc_get_auth_oid(int hashtype, int *oid_len):
408  *
409  * Given a type, return the OID and optionally set OID length.
410  */
411 oid *
sc_get_auth_oid(int type,size_t * oid_len)412 sc_get_auth_oid(int type, size_t *oid_len)
413 {
414     netsnmp_auth_alg_info *ai;
415 
416     DEBUGTRACE;
417 
418     ai = sc_find_auth_alg_bytype(type);
419     if (NULL == ai)
420         return NULL;
421 
422     if (NULL != oid_len)
423         *oid_len = ai->oid_len;
424 
425     return ai->alg_oid;
426 }
427 
428 /*
429  * sc_get_auth_name(int hashtype):
430  *
431  * Given a type, return the name string
432  */
433 const char*
sc_get_auth_name(int type)434 sc_get_auth_name(int type)
435 {
436     netsnmp_auth_alg_info *ai;
437 
438     DEBUGTRACE;
439 
440     ai = sc_find_auth_alg_bytype(type);
441     if (NULL == ai)
442         return NULL;
443 
444     return ai->name;
445 }
446 
447 /*
448  * sc_get_priv_oid(int type, int *oid_len):
449  *
450  * Given a type, return the OID and optionally set OID length.
451  */
452 oid *
sc_get_priv_oid(int type,size_t * oid_len)453 sc_get_priv_oid(int type, size_t *oid_len)
454 {
455     netsnmp_priv_alg_info *ai;
456 
457     DEBUGTRACE;
458 
459     ai = sc_get_priv_alg_bytype(type);
460     if (NULL == ai)
461         return NULL;
462 
463     if (NULL != oid_len)
464         *oid_len = ai->oid_len;
465 
466     return ai->alg_oid;
467 }
468 
469 /*
470  * sc_get_properlength(oid *hashtype, u_int hashtype_len):
471  *
472  * Given a hashing type ("hashtype" and its length hashtype_len), return
473  * the length of the hash result.
474  *
475  * Returns either the length or SNMPERR_GENERR for an unknown hashing type.
476  */
477 int
sc_get_properlength(const oid * hashtype,u_int hashtype_len)478 sc_get_properlength(const oid * hashtype, u_int hashtype_len)
479 {
480     DEBUGTRACE;
481     /*
482      * Determine transform type hash length.
483      */
484     return sc_get_proper_auth_length_bytype(
485         sc_get_authtype(hashtype, hashtype_len));
486 }
487 
488 netsnmp_feature_child_of(scapi_get_proper_priv_length, netsnmp_unused);
489 #ifndef NETSNMP_FEATURE_REMOVE_SCAPI_GET_PROPER_PRIV_LENGTH
490 int
sc_get_proper_priv_length(const oid * privtype,u_int privtype_len)491 sc_get_proper_priv_length(const oid * privtype, u_int privtype_len)
492 {
493     netsnmp_priv_alg_info *pai;
494 
495     DEBUGTRACE;
496 
497     pai = sc_get_priv_alg_byoid(privtype, privtype_len);
498     if (NULL == pai)
499         return 0;
500 
501     return pai->proper_length;
502 }
503 #endif /* NETSNMP_FEATURE_REMOVE_SCAPI_GET_PROPER_PRIV_LENGTH */
504 
505 /*
506  * sc_get_priv_alg_byindex(u_int index)
507  *
508  * returns a pointer to a netsnmp_priv_alg_info struct
509  */
510 netsnmp_priv_alg_info *
sc_get_priv_alg_byindex(u_int index)511 sc_get_priv_alg_byindex(u_int index)
512 {
513     DEBUGTRACE;
514 
515     if (index >= (sizeof(_priv_alg_info)) / (sizeof(_priv_alg_info[0])) ||
516         -1 == _priv_alg_info[index].type)
517         return NULL;
518 
519     return(&_priv_alg_info[index]);
520 }
521 
522 int
sc_get_proper_priv_length_bytype(int privtype)523 sc_get_proper_priv_length_bytype(int privtype)
524 {
525     netsnmp_priv_alg_info *pai;
526 
527     DEBUGTRACE;
528 
529     pai = sc_get_priv_alg_bytype(privtype);
530     if (NULL == pai)
531         return 0;
532 
533     return pai->proper_length;
534 }
535 
536 
537 /*******************************************************************-o-******
538  * sc_init
539  *
540  * Returns:
541  *	SNMPERR_SUCCESS			Success.
542  */
543 int
sc_init(void)544 sc_init(void)
545 {
546     int             rval = SNMPERR_SUCCESS;
547 
548 #if !defined(NETSNMP_USE_OPENSSL)
549 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
550     struct timeval  tv;
551 
552     DEBUGTRACE;
553 
554     gettimeofday(&tv, (struct timezone *) 0);
555 
556     netsnmp_srandom((unsigned)(tv.tv_sec ^ tv.tv_usec));
557 #elif NETSNMP_USE_PKCS11
558     DEBUGTRACE;
559     rval = pkcs_init();
560 #else
561     rval = SNMPERR_SC_NOT_CONFIGURED;
562 #endif                           /* NETSNMP_USE_INTERNAL_MD5 */
563     /*
564      * XXX ogud: The only reason to do anything here with openssl is to
565      * * XXX ogud: seed random number generator
566      */
567 #endif                          /* ifndef NETSNMP_USE_OPENSSL */
568 
569     return rval;
570 }                               /* end sc_init() */
571 
572 /*******************************************************************-o-******
573  * sc_random
574  *
575  * Parameters:
576  *	*buf		Pre-allocated buffer.
577  *	*buflen 	Size of buffer.
578  *
579  * Returns:
580  *	SNMPERR_SUCCESS			Success.
581  */
582 int
sc_random(u_char * buf,size_t * buflen)583 sc_random(u_char * buf, size_t * buflen)
584 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
585 {
586     int             rval = SNMPERR_SUCCESS;
587 #if !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_PKCS11)
588     int             i;
589     int             rndval;
590     u_char         *ucp = buf;
591 #endif
592 
593     DEBUGTRACE;
594 
595 #ifdef NETSNMP_USE_OPENSSL
596     RAND_bytes(buf, *buflen);   /* will never fail */
597     MAKE_MEM_DEFINED(buf, *buflen);
598 #elif NETSNMP_USE_PKCS11			/* NETSNMP_USE_PKCS11 */
599     pkcs_random(buf, *buflen);
600 #else                           /* NETSNMP_USE_INTERNAL_MD5 */
601     /*
602      * fill the buffer with random integers.  Note that random()
603      * is defined in config.h and may not be truly the random()
604      * system call if something better existed
605      */
606     rval = *buflen - *buflen % sizeof(rndval);
607     for (i = 0; i < rval; i += sizeof(rndval)) {
608         rndval = netsnmp_random();
609         memcpy(ucp, &rndval, sizeof(rndval));
610         ucp += sizeof(rndval);
611     }
612 
613     rndval = netsnmp_random();
614     memcpy(ucp, &rndval, *buflen % sizeof(rndval));
615 
616     rval = SNMPERR_SUCCESS;
617 #endif                          /* NETSNMP_USE_OPENSSL */
618     return rval;
619 
620 }                               /* end sc_random() */
621 
622 #else
623 _SCAPI_NOT_CONFIGURED
624 #endif                          /*  */
625 
626 
627 #ifdef NETSNMP_USE_OPENSSL
628 const EVP_MD   *
sc_get_openssl_hashfn(int auth_type)629 sc_get_openssl_hashfn(int auth_type)
630 {
631     const EVP_MD   *hashfn = NULL;
632 
633     DEBUGTRACE;
634 
635     switch (auth_type) {
636 #ifndef NETSNMP_DISABLE_MD5
637         case NETSNMP_USMAUTH_HMACMD5:
638             hashfn = (const EVP_MD *) EVP_md5();
639             break;
640 #endif
641         case NETSNMP_USMAUTH_HMACSHA1:
642             hashfn = (const EVP_MD *) EVP_sha1();
643             break;
644 
645 #ifdef HAVE_EVP_SHA224
646         case NETSNMP_USMAUTH_HMAC128SHA224:
647             hashfn = (const EVP_MD *) EVP_sha224();
648             break;
649 
650         case NETSNMP_USMAUTH_HMAC192SHA256:
651             hashfn = (const EVP_MD *) EVP_sha256();
652             break;
653 #endif /* HAVE_EVP_SHA224 */
654 
655 #ifdef HAVE_EVP_SHA384
656         case NETSNMP_USMAUTH_HMAC256SHA384:
657             hashfn = (const EVP_MD *) EVP_sha384();
658             break;
659 
660         case NETSNMP_USMAUTH_HMAC384SHA512:
661             hashfn = (const EVP_MD *) EVP_sha512();
662             break;
663 #endif /* HAVE_EVP_SHA384 */
664     }
665 
666     return hashfn;
667 }
668 
669 const EVP_CIPHER *
sc_get_openssl_privfn(int priv_type)670 sc_get_openssl_privfn(int priv_type)
671 {
672     const EVP_CIPHER *fn = NULL;
673 
674     DEBUGTRACE;
675 
676     switch(priv_type & (USM_PRIV_MASK_ALG | USM_PRIV_MASK_VARIANT)) {
677 #ifdef HAVE_AES
678         case USM_CREATE_USER_PRIV_AES:
679             fn = (const EVP_CIPHER *)EVP_aes_128_cfb();
680             break;
681 #ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
682         case USM_CREATE_USER_PRIV_AES192:
683             fn = (const void*)EVP_aes_192_cfb();
684             break;
685         case USM_CREATE_USER_PRIV_AES256:
686             fn = (const void*)EVP_aes_256_cfb();
687             break;
688 #endif
689 #endif /* HAVE_AES */
690     }
691 
692     return fn;
693 }
694 #endif /* openssl */
695 
696 
697 /*******************************************************************-o-******
698  * sc_generate_keyed_hash
699  *
700  * Parameters:
701  *	 authtype	Type of authentication transform.
702  *	 authtypelen
703  *	*key		Pointer to key (Kul) to use in keyed hash.
704  *	 keylen		Length of key in bytes.
705  *	*message	Pointer to the message to hash.
706  *	 msglen		Length of the message.
707  *	*MAC		Will be returned with allocated bytes containg hash.
708  *	*maclen		Length of the hash buffer in bytes; also indicates
709  *				whether the MAC should be truncated.
710  *
711  * Returns:
712  *	SNMPERR_SUCCESS			Success.
713  *	SNMPERR_GENERR			All errs
714  *
715  *
716  * A hash of the first msglen bytes of message using a keyed hash defined
717  * by authtype is created and stored in MAC.  MAC is ASSUMED to be a buffer
718  * of at least maclen bytes.  If the length of the hash is greater than
719  * maclen, it is truncated to fit the buffer.  If the length of the hash is
720  * less than maclen, maclen set to the number of hash bytes generated.
721  *
722  * ASSUMED that the number of hash bits is a multiple of 8.
723  */
724 int
sc_generate_keyed_hash(const oid * authtypeOID,size_t authtypeOIDlen,const u_char * key,u_int keylen,const u_char * message,u_int msglen,u_char * MAC,size_t * maclen)725 sc_generate_keyed_hash(const oid * authtypeOID, size_t authtypeOIDlen,
726                        const u_char * key, u_int keylen,
727                        const u_char * message, u_int msglen,
728                        u_char * MAC, size_t * maclen)
729 #if  defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
730 {
731     int             rval = SNMPERR_SUCCESS, auth_type;
732     int             iproperlength;
733     size_t          properlength;
734     u_char          buf[SNMP_MAXBUF_SMALL];
735 #if  defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11)
736     unsigned int    buf_len = sizeof(buf);
737 #endif
738 #ifdef NETSNMP_USE_OPENSSL
739     const EVP_MD   *hashfn;
740 #elif defined(NETSNMP_USE_PKCS11)
741     u_long          ck_type;
742 #endif
743 
744     DEBUGTRACE;
745 
746 #ifdef NETSNMP_ENABLE_TESTING_CODE
747     {
748         int             i;
749         DEBUGMSG(("sc_generate_keyed_hash",
750                   "sc_generate_keyed_hash(): key=0x"));
751         for (i = 0; i < keylen; i++)
752             DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff));
753         DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen));
754     }
755 #endif                          /* NETSNMP_ENABLE_TESTING_CODE */
756 
757     /*
758      * Sanity check.
759      */
760     if (!authtypeOID || !key || !message || !MAC || !maclen
761         || (keylen <= 0) || (msglen <= 0) || (*maclen <= 0)) {
762         QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
763     }
764 
765     auth_type = sc_get_authtype(authtypeOID, authtypeOIDlen);
766     iproperlength = sc_get_auth_maclen(auth_type);
767     if (iproperlength == SNMPERR_GENERR)
768         return SNMPERR_GENERR;
769     properlength = (size_t)iproperlength;
770     if (keylen < properlength) {
771         QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
772     }
773 #ifdef NETSNMP_ENABLE_TESTING_CODE
774     DEBUGMSGTL(("scapi", "iproperlength: %d, maclen:%" NETSNMP_PRIz "d\n", iproperlength,
775                 *maclen));
776 #endif
777 #ifdef NETSNMP_USE_OPENSSL
778     /** get hash function */
779     hashfn = sc_get_openssl_hashfn(auth_type);
780     if (NULL == hashfn) {
781         QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
782     }
783 
784     HMAC(hashfn, key, keylen, message, msglen, buf, &buf_len);
785     if (buf_len != properlength) {
786         QUITFUN(rval, sc_generate_keyed_hash_quit);
787     }
788     if (*maclen > buf_len)
789         *maclen = buf_len;
790     memcpy(MAC, buf, *maclen);
791 
792 #elif NETSNMP_USE_PKCS11                    /* NETSNMP_USE_PKCS11 */
793 
794 #ifndef NETSNMP_DISABLE_MD5
795     if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
796 	if (pkcs_sign(CKM_MD5_HMAC,key, keylen, message,
797 			msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
798             QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
799         }
800     } else
801 #endif
802         if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
803 	if (pkcs_sign(CKM_SHA_1_HMAC,key, keylen, message,
804 			msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
805             QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
806         }
807     } else {
808         QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
809     }
810 
811     if (buf_len != properlength) {
812         QUITFUN(rval, sc_generate_keyed_hash_quit);
813     }
814     if (*maclen > buf_len)
815         *maclen = buf_len;
816     memcpy(MAC, buf, *maclen);
817 
818 #elif NETSNMP_USE_INTERNAL_CRYPTO
819     if (*maclen > properlength)
820         *maclen = properlength;
821 #ifndef NETSNMP_DISABLE_MD5
822     if (NETSNMP_USMAUTH_HMACMD5 == auth_type)
823         rval = MD5_hmac(message, msglen, MAC, *maclen, key, keylen);
824     else
825 #endif
826          if (NETSNMP_USMAUTH_HMACSHA1 == auth_type)
827         rval = SHA1_hmac(message, msglen, MAC, *maclen, key, keylen);
828     else {
829         QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
830     }
831     if (rval != 0) {
832         rval = SNMPERR_GENERR;
833         goto sc_generate_keyed_hash_quit;
834     }
835 #else                            /* NETSNMP_USE_INTERNAL_MD5 */
836     if (*maclen > properlength)
837         *maclen = properlength;
838     if (MDsign(message, msglen, MAC, *maclen, key, keylen)) {
839         rval = SNMPERR_GENERR;
840         goto sc_generate_keyed_hash_quit;
841     }
842 #endif                          /* NETSNMP_USE_OPENSSL */
843 
844 #ifdef NETSNMP_ENABLE_TESTING_CODE
845     {
846         char           *s;
847         int             len = binary_to_hex(MAC, *maclen, &s);
848 
849         DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s));
850         SNMP_ZERO(s, len);
851         SNMP_FREE(s);
852     }
853 #endif                          /* NETSNMP_ENABLE_TESTING_CODE */
854 
855   sc_generate_keyed_hash_quit:
856     memset(buf, 0, SNMP_MAXBUF_SMALL);
857     return rval;
858 }                               /* end sc_generate_keyed_hash() */
859 
860 #else
861                 _SCAPI_NOT_CONFIGURED
862 #endif                          /* */
863 /*******************************************************************-o-******
864  * sc_hash(): a generic wrapper around whatever hashing package we are using.
865  *
866  * IN:
867  * hashtype    - oid pointer to a hash type
868  * hashtypelen - length of oid pointer
869  * buf         - u_char buffer to be hashed
870  * buf_len     - integer length of buf data
871  * MAC_len     - length of the passed MAC buffer size.
872  *
873  * OUT:
874  * MAC         - pre-malloced space to store hash output.
875  * MAC_len     - length of MAC output to the MAC buffer.
876  *
877  * Returns:
878  * SNMPERR_SUCCESS              Success.
879  * SNMP_SC_GENERAL_FAILURE      Any error.
880  * SNMPERR_SC_NOT_CONFIGURED    Hash type not supported.
881  */
882 int
sc_hash(const oid * hashtype,size_t hashtypelen,const u_char * buf,size_t buf_len,u_char * MAC,size_t * MAC_len)883 sc_hash(const oid * hashtype, size_t hashtypelen, const u_char * buf,
884         size_t buf_len, u_char * MAC, size_t * MAC_len)
885 {
886     int auth_type;
887 
888     DEBUGTRACE;
889 
890     if (hashtype == NULL)
891         return (SNMPERR_GENERR);
892 
893     auth_type = sc_get_authtype(hashtype, hashtypelen);
894     if (auth_type < 0 )
895         return (SNMPERR_GENERR);
896 
897     return sc_hash_type(auth_type, buf, buf_len, MAC, MAC_len);
898 }
899 
900 /*******************************************************************-o-******
901  * sc_hash_type():
902  *    a generic wrapper around whatever hashing package we are using.
903  *
904  * IN:
905  * hashtype    - oid pointer to a hash type
906  * hashtypelen - length of oid pointer
907  * buf         - u_char buffer to be hashed
908  * buf_len     - integer length of buf data
909  * MAC_len     - length of the passed MAC buffer size.
910  *
911  * OUT:
912  * MAC         - pre-malloced space to store hash output.
913  * MAC_len     - length of MAC output to the MAC buffer.
914  *
915  * Returns:
916  * SNMPERR_SUCCESS              Success.
917  * SNMP_SC_GENERAL_FAILURE      Any error.
918  * SNMPERR_SC_NOT_CONFIGURED    Hash type not supported.
919  */
920 int
sc_hash_type(int auth_type,const u_char * buf,size_t buf_len,u_char * MAC,size_t * MAC_len)921 sc_hash_type(int auth_type, const u_char * buf, size_t buf_len, u_char * MAC,
922              size_t * MAC_len)
923 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
924 {
925 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
926     int            rval = SNMPERR_SUCCESS;
927 #endif
928 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11)
929     unsigned int   tmp_len;
930 #endif
931     int            ret;
932 
933 #ifdef NETSNMP_USE_OPENSSL
934     const EVP_MD   *hashfn;
935     EVP_MD_CTX     *cptr;
936 #endif
937 #ifdef NETSNMP_USE_INTERNAL_CRYPTO
938     MD5_CTX        cmd5;
939     SHA_CTX        csha1;
940 #endif
941     DEBUGTRACE;
942 
943     if (buf == NULL || buf_len <= 0 || MAC == NULL || MAC_len == NULL )
944         return (SNMPERR_GENERR);
945 
946     ret = sc_get_proper_auth_length_bytype(auth_type);
947     if (( ret < 0 ) || (*MAC_len < (size_t)ret ))
948         return (SNMPERR_GENERR);
949 
950 #ifdef NETSNMP_USE_OPENSSL
951     /*
952      * Determine transform type.
953      */
954     hashfn = sc_get_openssl_hashfn(auth_type);
955     if (NULL == hashfn)
956         return SNMPERR_GENERR;
957 
958 /** initialize the pointer */
959 #if defined(HAVE_EVP_MD_CTX_NEW)
960     cptr = EVP_MD_CTX_new();
961 #elif defined(HAVE_EVP_MD_CTX_CREATE)
962     cptr = EVP_MD_CTX_create();
963 #else
964     cptr = malloc(sizeof(*cptr));
965 #if defined(OLD_DES)
966     memset(cptr, 0, sizeof(*cptr));
967 #else
968     EVP_MD_CTX_init(cptr);
969 #endif
970 #endif
971     if (!EVP_DigestInit(cptr, hashfn)) {
972         /* requested hash function is not available */
973         rval = SNMPERR_SC_NOT_CONFIGURED;
974         goto sc_hash_type_quit;
975     }
976 
977 /** pass the data */
978     EVP_DigestUpdate(cptr, buf, buf_len);
979 
980 /** do the final pass */
981     EVP_DigestFinal(cptr, MAC, &tmp_len);
982     *MAC_len = tmp_len;
983 
984 sc_hash_type_quit:
985 #if defined(HAVE_EVP_MD_CTX_FREE)
986     EVP_MD_CTX_free(cptr);
987 #elif defined(HAVE_EVP_MD_CTX_DESTROY)
988     EVP_MD_CTX_destroy(cptr);
989 #else
990 #if !defined(OLD_DES)
991     EVP_MD_CTX_cleanup(cptr);
992 #endif
993     free(cptr);
994 #endif
995     return (rval);
996 
997 #elif NETSNMP_USE_INTERNAL_CRYPTO
998 #ifndef NETSNMP_DISABLE_MD5
999     if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
1000         if (*MAC_len < MD5_DIGEST_LENGTH)
1001             return (SNMPERR_GENERR);      /* the buffer isn't big enough */
1002         MD5_Init(&cmd5);
1003         MD5_Update(&cmd5, buf, buf_len);
1004         MD5_Final(MAC, &cmd5);
1005         *MAC_len = MD5_DIGEST_LENGTH;
1006     } else
1007 #endif
1008     if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
1009         if (*MAC_len < SHA_DIGEST_LENGTH)
1010             return (SNMPERR_GENERR);      /* the buffer isn't big enough */
1011         SHA1_Init(&csha1);
1012         SHA1_Update(&csha1, buf, buf_len);
1013         SHA1_Final(MAC, &csha1);
1014         *MAC_len = SHA_DIGEST_LENGTH;
1015 
1016     } else {
1017         return (SNMPERR_GENERR);
1018     }
1019     return (rval);
1020 #elif NETSNMP_USE_PKCS11                  /* NETSNMP_USE_PKCS11 */
1021 
1022 #ifndef NETSNMP_DISABLE_MD5
1023     if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
1024         rval = pkcs_digest(CKM_MD5, buf, buf_len, MAC, &tmp_len);
1025         *MAC_len = tmp_len;
1026     } else
1027 #endif
1028     if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
1029        rval = pkcs_digest(CKM_SHA_1, buf, buf_len, MAC, &tmp_len);
1030         *MAC_len = tmp_len;
1031     } else {
1032         return (SNMPERR_GENERR);
1033     }
1034 
1035      return (rval);
1036 
1037 #else                           /* NETSNMP_USE_INTERNAL_MD5 */
1038 
1039     if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
1040         return SNMPERR_GENERR;
1041     }
1042     if (*MAC_len > 16)
1043         *MAC_len = 16;
1044     return SNMPERR_SUCCESS;
1045 
1046 #endif                          /* NETSNMP_USE_OPENSSL */
1047 }
1048 #else                           /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */
1049 _SCAPI_NOT_CONFIGURED
1050 #endif                          /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */
1051 /*******************************************************************-o-******
1052  * sc_check_keyed_hash
1053  *
1054  * Parameters:
1055  *	 authtype	Transform type of authentication hash.
1056  *	*key		Key bits in a string of bytes.
1057  *	 keylen		Length of key in bytes.
1058  *	*message	Message for which to check the hash.
1059  *	 msglen		Length of message.
1060  *	*MAC		Given hash.
1061  *	 maclen		Length of given hash; indicates truncation if it is
1062  *				shorter than the normal size of output for
1063  *				given hash transform.
1064  * Returns:
1065  *	SNMPERR_SUCCESS		Success.
1066  *	SNMP_SC_GENERAL_FAILURE	Any error
1067  *
1068  *
1069  * Check the hash given in MAC against the hash of message.  If the length
1070  * of MAC is less than the length of the transform hash output, only maclen
1071  * bytes are compared.  The length of MAC cannot be greater than the
1072  * length of the hash transform output.
1073  */
1074 int
sc_check_keyed_hash(const oid * authtypeOID,size_t authtypeOIDlen,const u_char * key,u_int keylen,const u_char * message,u_int msglen,const u_char * MAC,u_int maclen)1075 sc_check_keyed_hash(const oid * authtypeOID, size_t authtypeOIDlen,
1076                     const u_char * key, u_int keylen,
1077                     const u_char * message, u_int msglen,
1078                     const u_char * MAC, u_int maclen)
1079 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
1080 {
1081     int             rval = SNMPERR_SUCCESS, auth_type, auth_size;
1082     size_t          buf_len = SNMP_MAXBUF_SMALL;
1083 
1084     u_char          buf[SNMP_MAXBUF_SMALL];
1085 
1086     DEBUGTRACE;
1087 
1088 #ifdef NETSNMP_ENABLE_TESTING_CODE
1089     {
1090         int             i;
1091         DEBUGMSG(("scapi", "sc_check_keyed_hash():    key=0x"));
1092         for (i = 0; i < keylen; i++)
1093             DEBUGMSG(("scapi", "%02x", key[i] & 0xff));
1094         DEBUGMSG(("scapi", " (%d)\n", keylen));
1095     }
1096 #endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1097 
1098     /*
1099      * Sanity check.
1100      */
1101     if (!authtypeOID || !key || !message || !MAC
1102         || (keylen <= 0) || (msglen <= 0) || (maclen <= 0)) {
1103         QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1104     }
1105 
1106     auth_type = sc_get_authtype(authtypeOID, authtypeOIDlen);
1107     if (auth_type < 0 )
1108         return (SNMPERR_GENERR);
1109 
1110     auth_size = sc_get_auth_maclen(auth_type);
1111     if (0 == auth_size || maclen != auth_size) {
1112         QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1113     }
1114 
1115     /*
1116      * Generate a full hash of the message, then compare
1117      * the result with the given MAC which may be shorter than
1118      * the full hash length.
1119      */
1120     rval = sc_generate_keyed_hash(authtypeOID, authtypeOIDlen, key, keylen,
1121                                   message, msglen, buf, &buf_len);
1122     QUITFUN(rval, sc_check_keyed_hash_quit);
1123 
1124     if (maclen > msglen) {
1125         QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1126 
1127     } else if (memcmp(buf, MAC, maclen) != 0) {
1128         QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1129     }
1130 
1131 
1132   sc_check_keyed_hash_quit:
1133     memset(buf, 0, SNMP_MAXBUF_SMALL);
1134 
1135     return rval;
1136 
1137 }                               /* end sc_check_keyed_hash() */
1138 
1139 #else
1140 _SCAPI_NOT_CONFIGURED
1141 #endif                          /* NETSNMP_USE_INTERNAL_MD5 */
1142 /*******************************************************************-o-******
1143  * sc_encrypt
1144  *
1145  * Parameters:
1146  *	 privtype	Type of privacy cryptographic transform.
1147  *	*key		Key bits for crypting.
1148  *	 keylen		Length of key (buffer) in bytes.
1149  *	*iv		IV bits for crypting.
1150  *	 ivlen		Length of iv (buffer) in bytes.
1151  *	*plaintext	Plaintext to crypt.
1152  *	 ptlen		Length of plaintext.
1153  *	*ciphertext	Ciphertext to crypt.
1154  *	*ctlen		Length of ciphertext.
1155  *
1156  * Returns:
1157  *	SNMPERR_SUCCESS			Success.
1158  *	SNMPERR_SC_NOT_CONFIGURED	Encryption is not supported.
1159  *	SNMPERR_SC_GENERAL_FAILURE	Any other error
1160  *
1161  *
1162  * Encrypt plaintext into ciphertext using key and iv.
1163  *
1164  * ctlen contains actual number of crypted bytes in ciphertext upon
1165  * successful return.
1166  */
1167 int
sc_encrypt(const oid * privtype,size_t privtypelen,u_char * key,u_int keylen,u_char * iv,u_int ivlen,const u_char * plaintext,u_int ptlen,u_char * ciphertext,size_t * ctlen)1168 sc_encrypt(const oid * privtype, size_t privtypelen,
1169            u_char * key, u_int keylen,
1170            u_char * iv, u_int ivlen,
1171            const u_char * plaintext, u_int ptlen,
1172            u_char * ciphertext, size_t * ctlen)
1173 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
1174 {
1175     int             rval = SNMPERR_SUCCESS;
1176     u_char          pad_block[128];      /* bigger than anything I need */
1177     u_char          my_iv[128];  /* ditto */
1178     netsnmp_priv_alg_info *pai = NULL;
1179 #ifndef NETSNMP_DISABLE_DES
1180     int             pad, plast, pad_size = 0;
1181 #ifdef OLD_DES
1182     DES_key_schedule key_sch;
1183 #else
1184     DES_key_schedule key_sched_store;
1185     DES_key_schedule *key_sch = &key_sched_store;
1186 #endif /* OLD_DES */
1187     DES_cblock       key_struct;
1188 #endif /* NETSNMP_DISABLE_DES */
1189 
1190     DEBUGTRACE;
1191 
1192     /*
1193      * Sanity check.
1194      */
1195 #if	!defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
1196     snmp_log(LOG_ERR, "Encryption support not enabled.(2)\n");
1197     return SNMPERR_SC_NOT_CONFIGURED;
1198 #endif
1199 
1200     if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
1201         || (keylen <= 0) || (ivlen <= 0) || (ivlen > sizeof(my_iv))
1202         || (ptlen <= 0) || (*ctlen <= 0)) {
1203         DEBUGMSGTL(("scapi:encrypt", "bad arguments 1\n"));
1204         QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1205     } else if (ptlen > *ctlen) {
1206         DEBUGMSGTL(("scapi:encrypt", "bad arguments 2\n"));
1207         QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1208     }
1209 #ifdef NETSNMP_ENABLE_TESTING_CODE
1210     {
1211         size_t          buf_len = 128, out_len = 0;
1212         u_char         *buf = (u_char *) malloc(buf_len);
1213 
1214         if (buf != NULL) {
1215             if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1216                                          iv, ivlen)) {
1217                 DEBUGMSGTL(("scapi", "encrypt: IV: %s\n", buf));
1218             } else {
1219                 DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]\n", buf));
1220             }
1221             out_len = 0;
1222             if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1223                                          key, keylen)) {
1224                 DEBUGMSG(("scapi", "key: %s\n", buf));
1225             } else {
1226                 DEBUGMSG(("scapi", "key: %s [TRUNCATED]\n", buf));
1227             }
1228             out_len = 0;
1229             if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1230                                          plaintext, 16)) {
1231                 DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf));
1232             } else {
1233                 DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n",
1234                             buf));
1235             }
1236             free(buf);
1237         } else {
1238             DEBUGMSGTL(("scapi",
1239                         "encrypt: malloc fail for debug output\n"));
1240         }
1241     }
1242 #endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1243 
1244 
1245     /*
1246      * Determine privacy transform.
1247      */
1248     pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1249     if (NULL == pai ||
1250         (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1251         DEBUGMSGTL(("scapi:encrypt",
1252                     "bad arguments 3 pai %p, keylen %d ivlen %d\n",
1253                     pai, keylen, ivlen));
1254         if (pai)
1255             DEBUGMSGTL(("scapi:encrypt", " pai: properlen %d, ivlen %d\n",
1256                         pai->proper_length, pai->iv_length));
1257 
1258         QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1259     }
1260 
1261     memset(my_iv, 0, sizeof(my_iv));
1262 
1263 #ifndef NETSNMP_DISABLE_DES
1264     if (USM_CREATE_USER_PRIV_DES == (pai->type & USM_PRIV_MASK_ALG)) {
1265 
1266         /*
1267          * now calculate the padding needed
1268          */
1269 
1270         pad_size = pai->pad_size;
1271         pad = pad_size - (ptlen % pad_size);
1272         plast = (int) ptlen - (pad_size - pad);
1273         if (pad == pad_size)
1274             pad = 0;
1275         if (ptlen + pad > *ctlen) {
1276             DEBUGMSGTL(("scapi:encrypt", "not enough space\n"));
1277             QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);    /* not enough space */
1278         }
1279         if (pad > 0) {              /* copy data into pad block if needed */
1280             memcpy(pad_block, plaintext + plast, pad_size - pad);
1281             memset(&pad_block[pad_size - pad], pad, pad);   /* filling in padblock */
1282         }
1283 
1284         memcpy(key_struct, key, sizeof(key_struct));
1285         (void) DES_key_sched(&key_struct, key_sch);
1286 
1287         memcpy(my_iv, iv, ivlen);
1288         /*
1289          * encrypt the data
1290          */
1291         DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch,
1292                          (DES_cblock *) my_iv, DES_ENCRYPT);
1293         if (pad > 0) {
1294             /*
1295              * then encrypt the pad block
1296              */
1297             DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size,
1298                              key_sch, (DES_cblock *) my_iv, DES_ENCRYPT);
1299             *ctlen = plast + pad_size;
1300         } else {
1301             *ctlen = plast;
1302         }
1303     }
1304 #endif
1305 #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_AES)
1306     if (USM_CREATE_USER_PRIV_AES == (pai->type & USM_PRIV_MASK_ALG)) {
1307         EVP_CIPHER_CTX *ctx;
1308         const EVP_CIPHER *cipher;
1309         int len, rc, enclen;
1310 
1311         cipher = sc_get_openssl_privfn(pai->type);
1312         if (NULL == cipher) {
1313             DEBUGMSGTL(("scapi:encrypt", "cipher not found\n"));
1314             QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1315         }
1316 
1317         memcpy(my_iv, iv, ivlen);
1318         /*
1319          * encrypt the data
1320          */
1321         ctx = EVP_CIPHER_CTX_new();
1322         if (!ctx) {
1323             DEBUGMSGTL(("scapi:encrypt", "openssl error: ctx_new\n"));
1324             QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1325         }
1326         rc = EVP_EncryptInit(ctx, cipher, key, my_iv);
1327         if (rc != 1) {
1328             DEBUGMSGTL(("scapi:encrypt", "openssl error: init\n"));
1329             EVP_CIPHER_CTX_free(ctx);
1330             QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1331         }
1332         rc = EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, ptlen);
1333         if (rc != 1) {
1334             DEBUGMSGTL(("scapi:encrypt", "openssl error: update\n"));
1335             EVP_CIPHER_CTX_free(ctx);
1336             QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1337         }
1338         enclen = len;
1339         rc = EVP_EncryptFinal(ctx, ciphertext + len, &len);
1340         if (rc != 1) {
1341             DEBUGMSGTL(("scapi:encrypt", "openssl error: final\n"));
1342             EVP_CIPHER_CTX_free(ctx);
1343             QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1344         }
1345         enclen += len;
1346         ptlen = enclen;
1347         /* Clean up */
1348         EVP_CIPHER_CTX_free(ctx);
1349         *ctlen = ptlen;
1350     }
1351 #endif
1352   sc_encrypt_quit:
1353     /*
1354      * clear memory just in case
1355      */
1356     memset(my_iv, 0, sizeof(my_iv));
1357     memset(pad_block, 0, sizeof(pad_block));
1358 #ifndef NETSNMP_DISABLE_DES
1359     memset(key_struct, 0, sizeof(key_struct));
1360 #ifdef OLD_DES
1361     memset(&key_sch, 0, sizeof(key_sch));
1362 #else
1363     memset(&key_sched_store, 0, sizeof(key_sched_store));
1364 #endif
1365 #endif
1366     return rval;
1367 
1368 }                               /* end sc_encrypt() */
1369 #elif defined(NETSNMP_USE_PKCS11)
1370 {
1371     int             rval = SNMPERR_SUCCESS, priv_type
1372     u_char	    pkcs_des_key[8];
1373     netsnmp_priv_alg_info *pai;
1374 
1375     DEBUGTRACE;
1376 
1377     /*
1378      * Sanity check.
1379      */
1380 #if	!defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
1381     snmp_log(LOG_ERR, "Encryption support not enabled.(1)\n");
1382     return SNMPERR_SC_NOT_CONFIGURED;
1383 #endif
1384 
1385     if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
1386         || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)) {
1387         QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1388     } else if (ptlen > *ctlen) {
1389         QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1390     }
1391 
1392     /*
1393      * Determine privacy transform.
1394      */
1395     pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1396     if (NULL == pai || USM_CREATE_USER_PRIV_DES != priv_type ||
1397         (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1398         QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1399     }
1400 
1401     memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
1402     memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
1403     rval = pkcs_encrpyt(CKM_DES_CBC, pkcs_des_key,
1404                         sizeof(pkcs_des_key), iv, ivlen, plaintext, ptlen,
1405                         ciphertext, ctlen);
1406 
1407   sc_encrypt_quit:
1408     return rval;
1409 }
1410 #else
1411 {
1412 #	if NETSNMP_USE_INTERNAL_MD5
1413     {
1414         snmp_log(LOG_ERR, "Encryption support not enabled.(3)\n");
1415         DEBUGMSGTL(("scapi", "Encrypt function not defined.\n"));
1416         return SNMPERR_SC_GENERAL_FAILURE;
1417     }
1418 
1419 #	else
1420     _SCAPI_NOT_CONFIGURED
1421 #	endif                   /* NETSNMP_USE_INTERNAL_MD5 */
1422 }
1423 #endif                          /* */
1424 
1425 
1426 
1427 /*******************************************************************-o-******
1428  * sc_decrypt
1429  *
1430  * Parameters:
1431  *	 privtype
1432  *	*key
1433  *	 keylen
1434  *	*iv
1435  *	 ivlen
1436  *	*ciphertext
1437  *	 ctlen
1438  *	*plaintext
1439  *	*ptlen
1440  *
1441  * Returns:
1442  *	SNMPERR_SUCCESS			Success.
1443  *	SNMPERR_SC_NOT_CONFIGURED	Encryption is not supported.
1444  *      SNMPERR_SC_GENERAL_FAILURE      Any other error
1445  *
1446  *
1447  * Decrypt ciphertext into plaintext using key and iv.
1448  *
1449  * ptlen contains actual number of plaintext bytes in plaintext upon
1450  * successful return.
1451  */
1452 int
sc_decrypt(const oid * privtype,size_t privtypelen,u_char * key,u_int keylen,u_char * iv,u_int ivlen,u_char * ciphertext,u_int ctlen,u_char * plaintext,size_t * ptlen)1453 sc_decrypt(const oid * privtype, size_t privtypelen,
1454            u_char * key, u_int keylen,
1455            u_char * iv, u_int ivlen,
1456            u_char * ciphertext, u_int ctlen,
1457            u_char * plaintext, size_t * ptlen)
1458 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
1459 {
1460 
1461     int             rval = SNMPERR_SUCCESS;
1462     u_char          my_iv[128];
1463 #ifndef NETSNMP_DISABLE_DES
1464 #ifdef OLD_DES
1465     DES_key_schedule key_sch;
1466 #else
1467     DES_key_schedule key_sched_store;
1468     DES_key_schedule *key_sch = &key_sched_store;
1469 #endif
1470     DES_cblock      key_struct;
1471 #endif
1472     netsnmp_priv_alg_info *pai = NULL;
1473 
1474     DEBUGTRACE;
1475 
1476     if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
1477         || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)) {
1478         DEBUGMSGTL(("scapi", "decrypt: arg sanity checks failed\n"));
1479         QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1480     }
1481 #ifdef NETSNMP_ENABLE_TESTING_CODE
1482     {
1483         size_t          buf_len = 128, out_len = 0;
1484         u_char         *buf = (u_char *) malloc(buf_len);
1485 
1486         if (buf != NULL) {
1487             if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1488                                          iv, ivlen)) {
1489                 DEBUGMSGTL(("scapi", "decrypt: IV: %s\n", buf));
1490             } else {
1491                 DEBUGMSGTL(("scapi", "decrypt: IV: %s [TRUNCATED]\n", buf));
1492             }
1493             out_len = 0;
1494             if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1495                                          key, keylen)) {
1496                 DEBUGMSG(("scapi", "key: %s\n", buf));
1497             } else {
1498                 DEBUGMSG(("scapi", "key: %s [TRUNCATED]\n", buf));
1499             }
1500             free(buf);
1501         } else {
1502             DEBUGMSGTL(("scapi",
1503                         "decrypt: malloc fail for debug output\n"));
1504         }
1505     }
1506 #endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1507 
1508     /*
1509      * Determine privacy transform.
1510      */
1511     pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1512     if (NULL == pai ||
1513         (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1514         QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1515     }
1516 
1517     memset(my_iv, 0, sizeof(my_iv));
1518 #ifndef NETSNMP_DISABLE_DES
1519     if (USM_CREATE_USER_PRIV_DES == (pai->type & USM_PRIV_MASK_ALG)) {
1520         memcpy(key_struct, key, sizeof(key_struct));
1521         (void) DES_key_sched(&key_struct, key_sch);
1522 
1523         memcpy(my_iv, iv, ivlen);
1524         DES_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch,
1525                         (DES_cblock *) my_iv, DES_DECRYPT);
1526         *ptlen = ctlen;
1527     }
1528 #endif
1529 #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_AES)
1530     if (USM_CREATE_USER_PRIV_AES == (pai->type & USM_PRIV_MASK_ALG)) {
1531         EVP_CIPHER_CTX *ctx;
1532         const EVP_CIPHER *cipher;
1533         int len, rc;
1534 
1535         cipher = sc_get_openssl_privfn(pai->type);
1536         if (NULL == cipher)
1537             QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1538 
1539         memcpy(my_iv, iv, ivlen);
1540         /*
1541          * decrypt the data
1542          */
1543         ctx = EVP_CIPHER_CTX_new();
1544         if (!ctx) {
1545             QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1546         }
1547         rc = EVP_DecryptInit(ctx, cipher, key, my_iv);
1548         if (rc != 1) {
1549             EVP_CIPHER_CTX_free(ctx);
1550             QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1551         }
1552         rc = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ctlen);
1553         if (rc != 1) {
1554             EVP_CIPHER_CTX_free(ctx);
1555             QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1556         }
1557         rc = EVP_DecryptFinal(ctx, plaintext + len, &len);
1558         if (rc != 1) {
1559             EVP_CIPHER_CTX_free(ctx);
1560             QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1561         }
1562         /* Clean up */
1563         EVP_CIPHER_CTX_free(ctx);
1564         *ptlen = ctlen;
1565     }
1566 #endif
1567 
1568     /*
1569      * exit cond
1570      */
1571   sc_decrypt_quit:
1572 #ifndef NETSNMP_DISABLE_DES
1573 #ifdef OLD_DES
1574     memset(&key_sch, 0, sizeof(key_sch));
1575 #else
1576     memset(&key_sched_store, 0, sizeof(key_sched_store));
1577 #endif
1578     memset(key_struct, 0, sizeof(key_struct));
1579 #endif
1580     memset(my_iv, 0, sizeof(my_iv));
1581     return rval;
1582 }				/* USE OPEN_SSL */
1583 #elif NETSNMP_USE_PKCS11                  /* USE PKCS */
1584 {
1585     int             rval = SNMPERR_SUCCESS;
1586     u_char	    pkcs_des_key[8];
1587     netsnmp_priv_alg_info *pai;
1588 
1589     DEBUGTRACE;
1590 
1591     if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
1592         || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)) {
1593         QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1594     }
1595 
1596     /*
1597      * Determine privacy transform.
1598      */
1599     pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1600     if (NULL == pai || USM_CREATE_USER_PRIV_DES != priv_type ||
1601         (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1602         QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1603     }
1604 
1605     memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
1606     memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
1607     rval = pkcs_decrpyt(CKM_DES_CBC, pkcs_des_key,
1608                         sizeof(pkcs_des_key), iv, ivlen, ciphertext,
1609                         ctlen, plaintext, ptlen);
1610     *ptlen = ctlen;
1611 
1612   sc_decrypt_quit:
1613     return rval;
1614 }				/* USE PKCS */
1615 #else
1616 {
1617 #if	!defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
1618     snmp_log(LOG_ERR, "Encryption support not enabled.(4)\n");
1619     return SNMPERR_SC_NOT_CONFIGURED;
1620 #else
1621 #	if NETSNMP_USE_INTERNAL_MD5
1622     {
1623         DEBUGMSGTL(("scapi", "Decryption function not defined.\n"));
1624         return SNMPERR_SC_GENERAL_FAILURE;
1625     }
1626 
1627 #	else
1628     _SCAPI_NOT_CONFIGURED
1629 #	endif                   /* NETSNMP_USE_INTERNAL_MD5 */
1630 #endif                          /*  */
1631 }
1632 #endif                          /* NETSNMP_USE_OPENSSL */
1633 
1634 #ifdef NETSNMP_USE_INTERNAL_CRYPTO
1635 
1636 /* These functions are basically copies of the MDSign() routine in
1637    md5.c modified to be used with the OpenSSL hashing functions.  The
1638    copyright below is from the md5.c file that these functions were
1639    taken from: */
1640 
1641 /*
1642  * ** **************************************************************************
1643  * ** md5.c -- Implementation of MD5 Message Digest Algorithm                 **
1644  * ** Updated: 2/16/90 by Ronald L. Rivest                                    **
1645  * ** (C) 1990 RSA Data Security, Inc.                                        **
1646  * ** **************************************************************************
1647  */
1648 
1649 /*
1650  * MD5_hmac(data, len, MD5): do a checksum on an arbirtrary amount
1651  * of data, and prepended with a secret in the standard fashion
1652  */
1653 static int
MD5_hmac(const u_char * data,size_t len,u_char * mac,size_t maclen,const u_char * secret,size_t secretlen)1654 MD5_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
1655          const u_char * secret, size_t secretlen)
1656 {
1657 #define MD5_HASHKEYLEN 64
1658 #define MD5_SECRETKEYLEN 16
1659 
1660     MD5_CTX         cmd5;
1661     u_char          K1[MD5_HASHKEYLEN];
1662     u_char          K2[MD5_HASHKEYLEN];
1663     u_char          extendedAuthKey[MD5_HASHKEYLEN];
1664     u_char          buf[MD5_HASHKEYLEN];
1665     size_t          i;
1666     const u_char   *cp;
1667     u_char         *newdata = NULL;
1668     int             rc = 0;
1669 
1670     DEBUGTRACE;
1671 
1672     /*
1673      * memset(K1,0,MD5_HASHKEYLEN);
1674      * memset(K2,0,MD5_HASHKEYLEN);
1675      * memset(buf,0,MD5_HASHKEYLEN);
1676      * memset(extendedAuthKey,0,MD5_HASHKEYLEN);
1677      */
1678 
1679     if (secretlen != MD5_SECRETKEYLEN || secret == NULL ||
1680         mac == NULL || data == NULL ||
1681         len <= 0 || maclen <= 0) {
1682         /*
1683          * DEBUGMSGTL(("md5","MD5 signing not properly initialized"));
1684          */
1685         return -1;
1686     }
1687 
1688     memset(extendedAuthKey, 0, MD5_HASHKEYLEN);
1689     memcpy(extendedAuthKey, secret, secretlen);
1690     for (i = 0; i < MD5_HASHKEYLEN; i++) {
1691         K1[i] = extendedAuthKey[i] ^ 0x36;
1692         K2[i] = extendedAuthKey[i] ^ 0x5c;
1693     }
1694 
1695     MD5_Init(&cmd5);
1696     rc = !MD5_Update(&cmd5, K1, MD5_HASHKEYLEN);
1697     if (rc)
1698         goto update_end;
1699 
1700     i = len;
1701     if (((uintptr_t) data) % sizeof(long) != 0) {
1702         /*
1703          * this relies on the ability to use integer math and thus we
1704          * must rely on data that aligns on 32-bit-word-boundries
1705          */
1706         newdata = netsnmp_memdup(data, len);
1707         cp = newdata;
1708     } else {
1709         cp = data;
1710     }
1711 
1712     while (i >= 64) {
1713         rc = !MD5_Update(&cmd5, cp, 64);
1714         if (rc)
1715             goto update_end;
1716         cp += 64;
1717         i -= 64;
1718     }
1719 
1720     rc = !MD5_Update(&cmd5, cp, i);
1721     if (rc)
1722         goto update_end;
1723 
1724     memset(buf, 0, MD5_HASHKEYLEN);
1725     MD5_Final(buf, &cmd5);
1726 
1727     MD5_Init(&cmd5);
1728     rc = !MD5_Update(&cmd5, K2, MD5_HASHKEYLEN);
1729     if (rc)
1730         goto update_end;
1731     rc = !MD5_Update(&cmd5, buf, MD5_SECRETKEYLEN);
1732     if (rc)
1733         goto update_end;
1734 
1735     /*
1736      * copy the sign checksum to the outgoing pointer
1737      */
1738     MD5_Final(buf, &cmd5);
1739     memcpy(mac, buf, maclen);
1740 
1741   update_end:
1742     memset(buf, 0, MD5_HASHKEYLEN);
1743     memset(K1, 0, MD5_HASHKEYLEN);
1744     memset(K2, 0, MD5_HASHKEYLEN);
1745     memset(extendedAuthKey, 0, MD5_HASHKEYLEN);
1746     memset(&cmd5, 0, sizeof(cmd5));
1747 
1748     if (newdata)
1749         free(newdata);
1750     return rc;
1751 }
1752 
1753 static int
SHA1_hmac(const u_char * data,size_t len,u_char * mac,size_t maclen,const u_char * secret,size_t secretlen)1754 SHA1_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
1755           const u_char * secret, size_t secretlen)
1756 {
1757 #define SHA1_HASHKEYLEN   64
1758 #define SHA1_SECRETKEYLEN 20
1759 
1760     SHA_CTX         csha1;
1761     u_char          K1[SHA1_HASHKEYLEN];
1762     u_char          K2[SHA1_HASHKEYLEN];
1763     u_char          extendedAuthKey[SHA1_HASHKEYLEN];
1764     u_char          buf[SHA1_HASHKEYLEN];
1765     size_t          i;
1766     const u_char   *cp;
1767     u_char         *newdata = NULL;
1768     int             rc = 0;
1769 
1770     DEBUGTRACE;
1771 
1772     /*
1773      * memset(K1,0,SHA1_HASHKEYLEN);
1774      * memset(K2,0,SHA1_HASHKEYLEN);
1775      * memset(buf,0,SHA1_HASHKEYLEN);
1776      * memset(extendedAuthKey,0,SHA1_HASHKEYLEN);
1777      */
1778 
1779     if (secretlen != SHA1_SECRETKEYLEN || secret == NULL ||
1780         mac == NULL || data == NULL ||
1781         len <= 0 || maclen <= 0) {
1782         /*
1783          * DEBUGMSGTL(("sha1","SHA1 signing not properly initialized"));
1784          */
1785         return -1;
1786     }
1787 
1788     memset(extendedAuthKey, 0, SHA1_HASHKEYLEN);
1789     memcpy(extendedAuthKey, secret, secretlen);
1790     for (i = 0; i < SHA1_HASHKEYLEN; i++) {
1791         K1[i] = extendedAuthKey[i] ^ 0x36;
1792         K2[i] = extendedAuthKey[i] ^ 0x5c;
1793     }
1794 
1795     SHA1_Init(&csha1);
1796     rc = !SHA1_Update(&csha1, K1, SHA1_HASHKEYLEN);
1797     if (rc)
1798         goto update_end;
1799 
1800     i = len;
1801     if (((uintptr_t) data) % sizeof(long) != 0) {
1802         /*
1803          * this relies on the ability to use integer math and thus we
1804          * must rely on data that aligns on 32-bit-word-boundries
1805          */
1806         newdata = netsnmp_memdup(data, len);
1807         cp = newdata;
1808     } else {
1809         cp = data;
1810     }
1811 
1812     while (i >= 64) {
1813         rc = !SHA1_Update(&csha1, cp, 64);
1814         if (rc)
1815             goto update_end;
1816         cp += 64;
1817         i -= 64;
1818     }
1819 
1820     rc = !SHA1_Update(&csha1, cp, i);
1821     if (rc)
1822         goto update_end;
1823 
1824     memset(buf, 0, SHA1_HASHKEYLEN);
1825     SHA1_Final(buf, &csha1);
1826 
1827     SHA1_Init(&csha1);
1828     rc = !SHA1_Update(&csha1, K2, SHA1_HASHKEYLEN);
1829     if (rc)
1830         goto update_end;
1831     rc = !SHA1_Update(&csha1, buf, SHA1_SECRETKEYLEN);
1832     if (rc)
1833         goto update_end;
1834 
1835     /*
1836      * copy the sign checksum to the outgoing pointer
1837      */
1838     SHA1_Final(buf, &csha1);
1839     memcpy(mac, buf, maclen);
1840 
1841   update_end:
1842     memset(buf, 0, SHA1_HASHKEYLEN);
1843     memset(K1, 0, SHA1_HASHKEYLEN);
1844     memset(K2, 0, SHA1_HASHKEYLEN);
1845     memset(extendedAuthKey, 0, SHA1_HASHKEYLEN);
1846     memset(&csha1, 0, sizeof(csha1));
1847 
1848     if (newdata)
1849         free(newdata);
1850     return rc;
1851 }
1852 #endif /* NETSNMP_USE_INTERNAL_CRYPTO */
1853 #endif /*  NETSNMP_FEATURE_REMOVE_USM_SCAPI  */
1854