Coverage Report

Created: 2025-10-13 06:35

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