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
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.
17
#include <net-snmp/net-snmp-config.h>
19
#include <sys/types.h>
31
#if TIME_WITH_SYS_TIME
33
# include <sys/timeb.h>
35
# include <sys/time.h>
40
# include <sys/time.h>
45
#ifdef HAVE_NETINET_IN_H
46
#include <netinet/in.h>
53
#include <net-snmp/types.h>
54
#include <net-snmp/output_api.h>
55
#include <net-snmp/utilities.h>
57
#ifdef USE_INTERNAL_MD5
58
#include <net-snmp/library/md5.h>
60
#include <net-snmp/library/snmp_api.h>
61
#include <net-snmp/library/callback.h>
62
#include <net-snmp/library/snmp_secmod.h>
63
#include <net-snmp/library/snmpusm.h>
64
#include <net-snmp/library/keytools.h>
65
#include <net-snmp/library/scapi.h>
66
#include <net-snmp/library/mib.h>
67
#include <net-snmp/library/transform_oids.h>
70
#include <openssl/hmac.h>
71
#include <openssl/evp.h>
72
#include <openssl/rand.h>
73
#include <openssl/des.h>
75
#include <openssl/aes.h>
78
#ifdef STRUCT_DES_KS_STRUCT_HAS_WEAK_KEY
79
/* these are older names for newer structures that exist in openssl .9.7 */
80
#define DES_key_schedule des_key_schedule
81
#define DES_cblock des_cblock
82
#define DES_key_sched des_key_sched
83
#define DES_ncbc_encrypt des_ncbc_encrypt
84
#define DES_cbc_encrypt des_cbc_encrypt
88
#endif /* HAVE_OPENSSL */
91
#include <security/cryptoki.h>
96
#define QUITFUN(e, l) \
97
if (e != SNMPERR_SUCCESS) { \
98
rval = SNMPERR_SC_GENERAL_FAILURE; \
105
* sc_get_properlength(oid *hashtype, u_int hashtype_len):
107
* Given a hashing type ("hashtype" and its length hashtype_len), return
108
* the length of the hash result.
110
* Returns either the length or SNMPERR_GENERR for an unknown hashing type.
113
sc_get_properlength(const oid * hashtype, u_int hashtype_len)
117
* Determine transform type hash length.
119
if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
120
return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5);
121
} else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
122
return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
124
return SNMPERR_GENERR;
128
/*******************************************************************-o-******
132
* SNMPERR_SUCCESS Success.
137
int rval = SNMPERR_SUCCESS;
140
#ifdef USE_INTERNAL_MD5
145
gettimeofday(&tv, (struct timezone *) 0);
147
srandom(tv.tv_sec ^ tv.tv_usec);
152
rval = SNMPERR_SC_NOT_CONFIGURED;
153
#endif /* USE_INTERNAL_MD5 */
155
* XXX ogud: The only reason to do anything here with openssl is to
156
* * XXX ogud: seed random number generator
158
#endif /* ifndef USE_OPENSSL */
160
} /* end sc_init() */
162
/*******************************************************************-o-******
166
* *buf Pre-allocated buffer.
167
* *buflen Size of buffer.
170
* SNMPERR_SUCCESS Success.
173
sc_random(u_char * buf, size_t * buflen)
174
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
176
int rval = SNMPERR_SUCCESS;
177
#ifdef USE_INTERNAL_MD5
186
RAND_bytes(buf, *buflen); /* will never fail */
187
#elif USE_PKCS /* USE_PKCS */
188
pkcs_random(buf, *buflen);
189
#else /* USE_INTERNAL_MD5 */
191
* fill the buffer with random integers. Note that random()
192
* is defined in config.h and may not be truly the random()
193
* system call if something better existed
195
rval = *buflen - *buflen % sizeof(rndval);
196
for (i = 0; i < rval; i += sizeof(rndval)) {
198
memcpy(ucp, &rndval, sizeof(rndval));
199
ucp += sizeof(rndval);
203
memcpy(ucp, &rndval, *buflen % sizeof(rndval));
205
rval = SNMPERR_SUCCESS;
206
#endif /* USE_OPENSSL */
209
} /* end sc_random() */
212
_SCAPI_NOT_CONFIGURED
214
/*******************************************************************-o-******
215
* sc_generate_keyed_hash
218
* authtype Type of authentication transform.
220
* *key Pointer to key (Kul) to use in keyed hash.
221
* keylen Length of key in bytes.
222
* *message Pointer to the message to hash.
223
* msglen Length of the message.
224
* *MAC Will be returned with allocated bytes containg hash.
225
* *maclen Length of the hash buffer in bytes; also indicates
226
* whether the MAC should be truncated.
229
* SNMPERR_SUCCESS Success.
230
* SNMPERR_GENERR All errs
233
* A hash of the first msglen bytes of message using a keyed hash defined
234
* by authtype is created and stored in MAC. MAC is ASSUMED to be a buffer
235
* of at least maclen bytes. If the length of the hash is greater than
236
* maclen, it is truncated to fit the buffer. If the length of the hash is
237
* less than maclen, maclen set to the number of hash bytes generated.
239
* ASSUMED that the number of hash bits is a multiple of 8.
242
sc_generate_keyed_hash(const oid * authtype, size_t authtypelen,
243
u_char * key, u_int keylen,
244
u_char * message, u_int msglen,
245
u_char * MAC, size_t * maclen)
246
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
248
int rval = SNMPERR_SUCCESS;
251
u_char buf[SNMP_MAXBUF_SMALL];
252
#if defined(USE_OPENSSL) || defined(USE_PKCS)
253
size_t buf_len = sizeof(buf);
258
#ifdef SNMP_TESTING_CODE
261
DEBUGMSG(("sc_generate_keyed_hash",
262
"sc_generate_keyed_hash(): key=0x"));
263
for (i = 0; i < keylen; i++)
264
DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff));
265
DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen));
267
#endif /* SNMP_TESTING_CODE */
272
if (!authtype || !key || !message || !MAC || !maclen
273
|| (keylen <= 0) || (msglen <= 0) || (*maclen <= 0)
274
|| (authtypelen != USM_LENGTH_OID_TRANSFORM)) {
275
QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
278
properlength = sc_get_properlength(authtype, authtypelen);
279
if (properlength == SNMPERR_GENERR)
282
if (((int) keylen < properlength)) {
283
QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
287
* Determine transform type.
289
if (ISTRANSFORM(authtype, HMACMD5Auth))
290
HMAC(EVP_md5(), key, keylen, message, msglen, buf, &buf_len);
291
else if (ISTRANSFORM(authtype, HMACSHA1Auth))
292
HMAC(EVP_sha1(), key, keylen, message, msglen, buf, &buf_len);
294
QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
296
if ((int)buf_len != properlength) {
297
QUITFUN(rval, sc_generate_keyed_hash_quit);
299
if ((int)*maclen > buf_len)
301
memcpy(MAC, buf, *maclen);
303
#elif USE_PKCS /* USE_PKCS */
305
if (ISTRANSFORM(authtype, HMACMD5Auth)) {
306
if (pkcs_sign(CKM_MD5_HMAC,key, keylen, message,
307
msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
308
QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
310
} else if (ISTRANSFORM(authtype, HMACSHA1Auth)) {
311
if (pkcs_sign(CKM_SHA_1_HMAC,key, keylen, message,
312
msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
313
QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
316
QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
319
if (buf_len != properlength) {
320
QUITFUN(rval, sc_generate_keyed_hash_quit);
322
if (*maclen > buf_len)
324
memcpy(MAC, buf, *maclen);
326
#else /* USE_INTERNAL_MD5 */
327
if ((int) *maclen > properlength)
328
*maclen = properlength;
329
if (MDsign(message, msglen, MAC, *maclen, key, keylen)) {
330
rval = SNMPERR_GENERR;
331
goto sc_generate_keyed_hash_quit;
333
#endif /* USE_OPENSSL */
335
#ifdef SNMP_TESTING_CODE
338
int len = binary_to_hex(MAC, *maclen, &s);
340
DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s));
344
#endif /* SNMP_TESTING_CODE */
346
sc_generate_keyed_hash_quit:
347
SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
349
} /* end sc_generate_keyed_hash() */
352
_SCAPI_NOT_CONFIGURED
355
* sc_hash(): a generic wrapper around whatever hashing package we are using.
358
* hashtype - oid pointer to a hash type
359
* hashtypelen - length of oid pointer
360
* buf - u_char buffer to be hashed
361
* buf_len - integer length of buf data
362
* MAC_len - length of the passed MAC buffer size.
365
* MAC - pre-malloced space to store hash output.
366
* MAC_len - length of MAC output to the MAC buffer.
369
* SNMPERR_SUCCESS Success.
370
* SNMP_SC_GENERAL_FAILURE Any error.
373
sc_hash(const oid * hashtype, size_t hashtypelen, u_char * buf,
374
size_t buf_len, u_char * MAC, size_t * MAC_len)
375
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
377
#if defined(USE_OPENSSL) || defined(USE_PKCS)
378
int rval = SNMPERR_SUCCESS;
382
const EVP_MD *hashfn;
383
EVP_MD_CTX ctx, *cptr;
388
if (hashtype == NULL || hashtypelen < 0 || buf == NULL ||
389
buf_len < 0 || MAC == NULL || MAC_len == NULL ||
390
(int) (*MAC_len) < sc_get_properlength(hashtype, hashtypelen))
391
return (SNMPERR_GENERR);
395
* Determine transform type.
397
if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
398
hashfn = (const EVP_MD *) EVP_md5();
399
} else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
400
hashfn = (const EVP_MD *) EVP_sha1();
402
return (SNMPERR_GENERR);
405
/** initialize the pointer */
406
memset(&ctx, 0, sizeof(ctx));
409
EVP_DigestInit(cptr, hashfn);
411
/* this is needed if the runtime library is different than the compiled
412
library since the openssl versions are very different. */
413
if (SSLeay() < 0x907000) {
414
/* the old version of the struct was bigger and thus more
415
memory is needed. should be 152, but we use 256 for safety. */
417
EVP_DigestInit(cptr, hashfn);
419
EVP_MD_CTX_init(cptr);
420
EVP_DigestInit(cptr, hashfn);
425
EVP_DigestUpdate(cptr, buf, buf_len);
427
/** do the final pass */
429
EVP_DigestFinal(cptr, MAC, MAC_len);
431
if (SSLeay() < 0x907000) {
432
EVP_DigestFinal(cptr, MAC, MAC_len);
435
EVP_DigestFinal_ex(cptr, MAC, MAC_len);
436
EVP_MD_CTX_cleanup(cptr);
440
#elif USE_PKCS /* USE_PKCS */
442
if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
443
rval = pkcs_digest(CKM_MD5, buf, buf_len, MAC, MAC_len);
444
} else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
445
rval = pkcs_digest(CKM_SHA_1, buf, buf_len, MAC, MAC_len);
447
return (SNMPERR_GENERR);
452
#else /* USE_INTERNAL_MD5 */
454
if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
455
return SNMPERR_GENERR;
459
return SNMPERR_SUCCESS;
461
#endif /* USE_OPENSSL */
463
#else /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */
464
_SCAPI_NOT_CONFIGURED
465
#endif /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */
466
/*******************************************************************-o-******
467
* sc_check_keyed_hash
470
* authtype Transform type of authentication hash.
471
* *key Key bits in a string of bytes.
472
* keylen Length of key in bytes.
473
* *message Message for which to check the hash.
474
* msglen Length of message.
476
* maclen Length of given hash; indicates truncation if it is
477
* shorter than the normal size of output for
478
* given hash transform.
480
* SNMPERR_SUCCESS Success.
481
* SNMP_SC_GENERAL_FAILURE Any error
484
* Check the hash given in MAC against the hash of message. If the length
485
* of MAC is less than the length of the transform hash output, only maclen
486
* bytes are compared. The length of MAC cannot be greater than the
487
* length of the hash transform output.
490
sc_check_keyed_hash(const oid * authtype, size_t authtypelen,
491
u_char * key, u_int keylen,
492
u_char * message, u_int msglen,
493
u_char * MAC, u_int maclen)
494
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
496
int rval = SNMPERR_SUCCESS;
497
size_t buf_len = SNMP_MAXBUF_SMALL;
499
u_char buf[SNMP_MAXBUF_SMALL];
503
#ifdef SNMP_TESTING_CODE
506
DEBUGMSG(("scapi", "sc_check_keyed_hash(): key=0x"));
507
for (i = 0; i < keylen; i++)
508
DEBUGMSG(("scapi", "%02x", key[i] & 0xff));
509
DEBUGMSG(("scapi", " (%d)\n", keylen));
511
#endif /* SNMP_TESTING_CODE */
516
if (!authtype || !key || !message || !MAC
517
|| (keylen <= 0) || (msglen <= 0) || (maclen <= 0)
518
|| (authtypelen != USM_LENGTH_OID_TRANSFORM)) {
519
QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
524
* Generate a full hash of the message, then compare
525
* the result with the given MAC which may shorter than
526
* the full hash length.
528
rval = sc_generate_keyed_hash(authtype, authtypelen,
530
message, msglen, buf, &buf_len);
531
QUITFUN(rval, sc_check_keyed_hash_quit);
533
if (maclen > msglen) {
534
QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
536
} else if (memcmp(buf, MAC, maclen) != 0) {
537
QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
541
sc_check_keyed_hash_quit:
542
SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
546
} /* end sc_check_keyed_hash() */
549
_SCAPI_NOT_CONFIGURED
550
#endif /* USE_INTERNAL_MD5 */
551
/*******************************************************************-o-******
555
* privtype Type of privacy cryptographic transform.
556
* *key Key bits for crypting.
557
* keylen Length of key (buffer) in bytes.
558
* *iv IV bits for crypting.
559
* ivlen Length of iv (buffer) in bytes.
560
* *plaintext Plaintext to crypt.
561
* ptlen Length of plaintext.
562
* *ciphertext Ciphertext to crypt.
563
* *ctlen Length of ciphertext.
566
* SNMPERR_SUCCESS Success.
567
* SNMPERR_SC_NOT_CONFIGURED Encryption is not supported.
568
* SNMPERR_SC_GENERAL_FAILURE Any other error
571
* Encrypt plaintext into ciphertext using key and iv.
573
* ctlen contains actual number of crypted bytes in ciphertext upon
577
sc_encrypt(const oid * privtype, size_t privtypelen,
578
u_char * key, u_int keylen,
579
u_char * iv, u_int ivlen,
580
u_char * plaintext, u_int ptlen,
581
u_char * ciphertext, size_t * ctlen)
582
#if defined(USE_OPENSSL)
584
int rval = SNMPERR_SUCCESS;
585
u_int properlength, properlength_iv;
586
u_char pad_block[128]; /* bigger than anything I need */
587
u_char my_iv[128]; /* ditto */
588
int pad, plast, pad_size = 0;
590
DES_key_schedule key_sch;
592
DES_key_schedule key_sched_store;
593
DES_key_schedule *key_sch = &key_sched_store;
595
DES_cblock key_struct;
606
#if !defined(SCAPI_AUTHPRIV)
607
snmp_log(LOG_ERR, "Encryption support not enabled.\n");
608
return SNMPERR_SC_NOT_CONFIGURED;
611
if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
612
|| (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)
613
|| (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
614
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
615
} else if (ptlen > *ctlen) {
616
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
618
#ifdef SNMP_TESTING_CODE
620
size_t buf_len = 128, out_len = 0;
621
u_char *buf = (u_char *) malloc(buf_len);
624
if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
626
DEBUGMSGTL(("scapi", "encrypt: IV: %s/", buf));
628
DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]/", buf));
631
if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
633
DEBUGMSG(("scapi", "%s\n", buf));
635
DEBUGMSG(("scapi", "%s [TRUNCATED]\n", buf));
638
if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
640
DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf));
642
DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n",
648
"encrypt: malloc fail for debug output\n"));
651
#endif /* SNMP_TESTING_CODE */
655
* Determine privacy transform.
657
if (ISTRANSFORM(privtype, DESPriv)) {
658
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
659
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
660
pad_size = properlength;
662
} else if (ISTRANSFORM(privtype, AES128Priv)) {
663
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128);
664
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128_IV);
665
} else if (ISTRANSFORM(privtype, AES192Priv)) {
666
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192);
667
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV);
668
} else if (ISTRANSFORM(privtype, AES256Priv)) {
669
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256);
670
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV);
673
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
676
if ((keylen < properlength) || (ivlen < properlength_iv)) {
677
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
680
memset(my_iv, 0, sizeof(my_iv));
682
if (ISTRANSFORM(privtype, DESPriv)) {
685
* now calculate the padding needed
687
pad = pad_size - (ptlen % pad_size);
688
plast = (int) ptlen - (pad_size - pad);
691
if (ptlen + pad > *ctlen) {
692
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); /* not enough space */
694
if (pad > 0) { /* copy data into pad block if needed */
695
memcpy(pad_block, plaintext + plast, pad_size - pad);
696
memset(&pad_block[pad_size - pad], pad, pad); /* filling in padblock */
699
memcpy(key_struct, key, sizeof(key_struct));
700
(void) DES_key_sched(&key_struct, key_sch);
702
memcpy(my_iv, iv, ivlen);
706
DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch,
707
(DES_cblock *) my_iv, DES_ENCRYPT);
710
* then encrypt the pad block
712
DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size,
713
key_sch, (DES_cblock *) my_iv, DES_ENCRYPT);
714
*ctlen = plast + pad_size;
720
else if (ISTRANSFORM(privtype, AES128Priv) ||
721
ISTRANSFORM(privtype, AES192Priv) ||
722
ISTRANSFORM(privtype, AES256Priv)) {
723
(void) AES_set_encrypt_key(key, properlength*8, &aes_key);
725
memcpy(my_iv, iv, ivlen);
729
AES_cfb128_encrypt(plaintext, ciphertext, ptlen,
730
&aes_key, my_iv, &new_ivlen, AES_ENCRYPT);
736
* clear memory just in case
738
memset(my_iv, 0, sizeof(my_iv));
739
memset(pad_block, 0, sizeof(pad_block));
740
memset(key_struct, 0, sizeof(key_struct));
742
memset(&key_sch, 0, sizeof(key_sch));
744
memset(&key_sched_store, 0, sizeof(key_sched_store));
747
memset(&aes_key,0,sizeof(aes_key));
751
} /* end sc_encrypt() */
752
#elif defined(USE_PKCS)
754
int rval = SNMPERR_SUCCESS;
755
u_int properlength, properlength_iv;
756
u_char pkcs_des_key[8];
763
#if !defined(SCAPI_AUTHPRIV)
764
snmp_log(LOG_ERR, "Encryption support not enabled.\n");
765
return SNMPERR_SC_NOT_CONFIGURED;
768
if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
769
|| (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)
770
|| (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
771
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
772
} else if (ptlen > *ctlen) {
773
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
777
* Determine privacy transform.
779
if (ISTRANSFORM(privtype, DESPriv)) {
780
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
781
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
783
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
786
if ((keylen < properlength) || (ivlen < properlength_iv)) {
787
QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
790
if (ISTRANSFORM(privtype, DESPriv)) {
791
memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
792
memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
793
rval = pkcs_encrpyt(CKM_DES_CBC, pkcs_des_key,
794
sizeof(pkcs_des_key), iv, ivlen, plaintext, ptlen,
803
# if USE_INTERNAL_MD5
805
snmp_log(LOG_ERR, "Encryption support not enabled.\n");
806
DEBUGMSGTL(("scapi", "Encrypt function not defined.\n"));
807
return SNMPERR_SC_GENERAL_FAILURE;
811
_SCAPI_NOT_CONFIGURED
812
# endif /* USE_INTERNAL_MD5 */
818
/*******************************************************************-o-******
833
* SNMPERR_SUCCESS Success.
834
* SNMPERR_SC_NOT_CONFIGURED Encryption is not supported.
835
* SNMPERR_SC_GENERAL_FAILURE Any other error
838
* Decrypt ciphertext into plaintext using key and iv.
840
* ptlen contains actual number of plaintext bytes in plaintext upon
844
sc_decrypt(const oid * privtype, size_t privtypelen,
845
u_char * key, u_int keylen,
846
u_char * iv, u_int ivlen,
847
u_char * ciphertext, u_int ctlen,
848
u_char * plaintext, size_t * ptlen)
852
int rval = SNMPERR_SUCCESS;
855
DES_key_schedule key_sch;
857
DES_key_schedule key_sched_store;
858
DES_key_schedule *key_sch = &key_sched_store;
860
DES_cblock key_struct;
861
u_int properlength, properlength_iv;
869
if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
870
|| (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)
871
|| (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
872
QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
874
#ifdef SNMP_TESTING_CODE
876
size_t buf_len = 128, out_len = 0;
877
u_char *buf = (u_char *) malloc(buf_len);
880
if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
882
DEBUGMSGTL(("scapi", "decrypt: IV: %s/", buf));
884
DEBUGMSGTL(("scapi", "decrypt: IV: %s [TRUNCATED]/", buf));
887
if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
889
DEBUGMSG(("scapi", "%s\n", buf));
891
DEBUGMSG(("scapi", "%s\n", buf));
896
"decrypt: malloc fail for debug output\n"));
899
#endif /* SNMP_TESTING_CODE */
902
* Determine privacy transform.
904
if (ISTRANSFORM(privtype, DESPriv)) {
905
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
906
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
908
} else if (ISTRANSFORM(privtype, AES128Priv)) {
909
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128);
910
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128_IV);
911
} else if (ISTRANSFORM(privtype, AES192Priv)) {
912
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192);
913
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV);
914
} else if (ISTRANSFORM(privtype, AES256Priv)) {
915
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256);
916
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV);
919
QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
922
if ((keylen < properlength) || (ivlen < properlength_iv)) {
923
QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
926
memset(my_iv, 0, sizeof(my_iv));
927
if (ISTRANSFORM(privtype, DESPriv)) {
928
memcpy(key_struct, key, sizeof(key_struct));
929
(void) DES_key_sched(&key_struct, key_sch);
931
memcpy(my_iv, iv, ivlen);
932
DES_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch,
933
(DES_cblock *) my_iv, DES_DECRYPT);
937
else if (ISTRANSFORM(privtype, AES128Priv) ||
938
ISTRANSFORM(privtype, AES192Priv) ||
939
ISTRANSFORM(privtype, AES256Priv)) {
940
(void) AES_set_encrypt_key(key, properlength*8, &aes_key);
942
memcpy(my_iv, iv, ivlen);
946
AES_cfb128_encrypt(ciphertext, plaintext, ctlen,
947
&aes_key, my_iv, &new_ivlen, AES_DECRYPT);
957
memset(&key_sch, 0, sizeof(key_sch));
959
memset(&key_sched_store, 0, sizeof(key_sched_store));
961
memset(key_struct, 0, sizeof(key_struct));
962
memset(my_iv, 0, sizeof(my_iv));
965
#elif USE_PKCS /* USE PKCS */
967
int rval = SNMPERR_SUCCESS;
968
u_int properlength, properlength_iv;
969
u_char pkcs_des_key[8];
973
if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
974
|| (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)
975
|| (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
976
QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
980
* Determine privacy transform.
982
if (ISTRANSFORM(privtype, DESPriv)) {
983
properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
984
properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
986
QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
989
if ((keylen < properlength) || (ivlen < properlength_iv)) {
990
QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
993
if (ISTRANSFORM(privtype, DESPriv)) {
994
memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
995
memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
996
rval = pkcs_decrpyt(CKM_DES_CBC, pkcs_des_key,
997
sizeof(pkcs_des_key), iv, ivlen, ciphertext,
998
ctlen, plaintext, ptlen);
1007
#if !defined(SCAPI_AUTHPRIV)
1008
snmp_log(LOG_ERR, "Encryption support not enabled.\n");
1009
return SNMPERR_SC_NOT_CONFIGURED;
1011
# if USE_INTERNAL_MD5
1013
DEBUGMSGTL(("scapi", "Decryption function not defined.\n"));
1014
return SNMPERR_SC_GENERAL_FAILURE;
1018
_SCAPI_NOT_CONFIGURED
1019
# endif /* USE_INTERNAL_MD5 */
1022
#endif /* USE_OPENSSL */