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