Coverage Report

Created: 2024-07-27 06:05

/src/net-snmp/snmplib/scapi.c
Line
Count
Source (jump to first uncovered line)
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
        MD5_Update(&cmd5, buf, buf_len);
1005
        MD5_Final(MAC, &cmd5);
1006
        *MAC_len = MD5_DIGEST_LENGTH;
1007
    } else 
1008
#endif
1009
    if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
1010
        if (*MAC_len < SHA_DIGEST_LENGTH)
1011
            return (SNMPERR_GENERR);      /* the buffer isn't big enough */
1012
        SHA1_Init(&csha1);
1013
        SHA1_Update(&csha1, buf, buf_len);
1014
        SHA1_Final(MAC, &csha1);
1015
        *MAC_len = SHA_DIGEST_LENGTH;
1016
            
1017
    } else {
1018
        return (SNMPERR_GENERR);
1019
    }
1020
    return (rval);
1021
#elif defined(NETSNMP_USE_PKCS11)        /* NETSNMP_USE_PKCS11 */
1022
1023
#ifndef NETSNMP_DISABLE_MD5
1024
    if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
1025
        rval = pkcs_digest(CKM_MD5, buf, buf_len, MAC, &tmp_len);
1026
        *MAC_len = tmp_len;
1027
    } else
1028
#endif
1029
    if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
1030
       rval = pkcs_digest(CKM_SHA_1, buf, buf_len, MAC, &tmp_len);
1031
        *MAC_len = tmp_len;
1032
    } else {
1033
        return (SNMPERR_GENERR);
1034
    }
1035
1036
     return (rval);
1037
1038
#else                           /* NETSNMP_USE_INTERNAL_MD5 */
1039
1040
    if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
1041
        return SNMPERR_GENERR;
1042
    }
1043
    if (*MAC_len > 16)
1044
        *MAC_len = 16;
1045
    return SNMPERR_SUCCESS;
1046
1047
#endif                          /* NETSNMP_USE_OPENSSL */
1048
0
}
1049
#else                           /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */
1050
_SCAPI_NOT_CONFIGURED
1051
#endif                          /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */
1052
/*******************************************************************-o-******
1053
 * sc_check_keyed_hash
1054
 *
1055
 * Parameters:
1056
 *   authtype Transform type of authentication hash.
1057
 *  *key    Key bits in a string of bytes.
1058
 *   keylen   Length of key in bytes.
1059
 *  *message  Message for which to check the hash.
1060
 *   msglen   Length of message.
1061
 *  *MAC    Given hash.
1062
 *   maclen   Length of given hash; indicates truncation if it is
1063
 *        shorter than the normal size of output for
1064
 *        given hash transform.
1065
 * Returns:
1066
 *  SNMPERR_SUCCESS   Success.
1067
 *  SNMP_SC_GENERAL_FAILURE Any error
1068
 *
1069
 *
1070
 * Check the hash given in MAC against the hash of message.  If the length
1071
 * of MAC is less than the length of the transform hash output, only maclen
1072
 * bytes are compared.  The length of MAC cannot be greater than the
1073
 * length of the hash transform output.
1074
 */
1075
int
1076
sc_check_keyed_hash(const oid * authtypeOID, size_t authtypeOIDlen,
1077
                    const u_char * key, u_int keylen,
1078
                    const u_char * message, u_int msglen,
1079
                    const u_char * MAC, u_int maclen)
1080
#if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
1081
0
{
1082
0
    int             rval = SNMPERR_SUCCESS, auth_type, auth_size;
1083
0
    size_t          buf_len = SNMP_MAXBUF_SMALL;
1084
1085
0
    u_char          buf[SNMP_MAXBUF_SMALL];
1086
1087
0
    DEBUGTRACE;
1088
1089
#ifdef NETSNMP_ENABLE_TESTING_CODE
1090
    {
1091
        int             i;
1092
        DEBUGMSG(("scapi", "sc_check_keyed_hash():    key=0x"));
1093
        for (i = 0; i < keylen; i++)
1094
            DEBUGMSG(("scapi", "%02x", key[i] & 0xff));
1095
        DEBUGMSG(("scapi", " (%d)\n", keylen));
1096
    }
1097
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1098
1099
    /*
1100
     * Sanity check.
1101
     */
1102
0
    if (!authtypeOID || !key || !message || !MAC
1103
0
        || (keylen <= 0) || (msglen <= 0) || (maclen <= 0)) {
1104
0
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1105
0
    }
1106
1107
0
    auth_type = sc_get_authtype(authtypeOID, authtypeOIDlen);
1108
0
    if (auth_type < 0 )
1109
0
        return (SNMPERR_GENERR);
1110
1111
0
    auth_size = sc_get_auth_maclen(auth_type);
1112
0
    if (0 == auth_size || maclen != auth_size) {
1113
0
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1114
0
    }
1115
1116
    /*
1117
     * Generate a full hash of the message, then compare
1118
     * the result with the given MAC which may be shorter than
1119
     * the full hash length.
1120
     */
1121
0
    rval = sc_generate_keyed_hash(authtypeOID, authtypeOIDlen, key, keylen,
1122
0
                                  message, msglen, buf, &buf_len);
1123
0
    QUITFUN(rval, sc_check_keyed_hash_quit);
1124
1125
0
    if (maclen > msglen) {
1126
0
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1127
1128
0
    } else if (memcmp(buf, MAC, maclen) != 0) {
1129
0
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
1130
0
    }
1131
1132
1133
0
  sc_check_keyed_hash_quit:
1134
0
    memset(buf, 0, SNMP_MAXBUF_SMALL);
1135
1136
0
    return rval;
1137
1138
0
}                               /* end sc_check_keyed_hash() */
1139
1140
#else
1141
_SCAPI_NOT_CONFIGURED
1142
#endif                          /* NETSNMP_USE_INTERNAL_MD5 */
1143
/*******************************************************************-o-******
1144
 * sc_encrypt
1145
 *
1146
 * Parameters:
1147
 *   privtype Type of privacy cryptographic transform.
1148
 *  *key    Key bits for crypting.
1149
 *   keylen   Length of key (buffer) in bytes.
1150
 *  *iv   IV bits for crypting.
1151
 *   ivlen    Length of iv (buffer) in bytes.
1152
 *  *plaintext  Plaintext to crypt.
1153
 *   ptlen    Length of plaintext.
1154
 *  *ciphertext Ciphertext to crypt.
1155
 *  *ctlen    Length of ciphertext.
1156
 *      
1157
 * Returns:
1158
 *  SNMPERR_SUCCESS     Success.
1159
 *  SNMPERR_SC_NOT_CONFIGURED Encryption is not supported.
1160
 *  SNMPERR_SC_GENERAL_FAILURE  Any other error
1161
 *
1162
 *
1163
 * Encrypt plaintext into ciphertext using key and iv.
1164
 *
1165
 * ctlen contains actual number of crypted bytes in ciphertext upon
1166
 * successful return.
1167
 */
1168
int
1169
sc_encrypt(const oid * privtype, size_t privtypelen,
1170
           u_char * key, u_int keylen,
1171
           u_char * iv, u_int ivlen,
1172
           const u_char * plaintext, u_int ptlen,
1173
           u_char * ciphertext, size_t * ctlen)
1174
#if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
1175
0
{
1176
0
    int             rval = SNMPERR_SUCCESS;
1177
0
    u_char          pad_block[128];      /* bigger than anything I need */
1178
0
    u_char          my_iv[128];  /* ditto */
1179
0
    const netsnmp_priv_alg_info *pai = NULL;
1180
0
#ifndef NETSNMP_DISABLE_DES
1181
0
    int             pad, plast, pad_size = 0;
1182
#ifdef OLD_DES
1183
    DES_key_schedule key_sch;
1184
#else
1185
0
    DES_key_schedule key_sched_store;
1186
0
    DES_key_schedule *key_sch = &key_sched_store;
1187
0
#endif /* OLD_DES */
1188
0
    DES_cblock       key_struct;
1189
0
#endif /* NETSNMP_DISABLE_DES */
1190
1191
0
    DEBUGTRACE;
1192
1193
    /*
1194
     * Sanity check.
1195
     */
1196
#if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
1197
    snmp_log(LOG_ERR, "Encryption support not enabled.(2)\n");
1198
    return SNMPERR_SC_NOT_CONFIGURED;
1199
#endif
1200
1201
0
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
1202
0
        || (keylen <= 0) || (ivlen <= 0) || (ivlen > sizeof(my_iv))
1203
0
        || (ptlen <= 0) || (*ctlen <= 0)) {
1204
0
        DEBUGMSGTL(("scapi:encrypt", "bad arguments 1\n"));
1205
0
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1206
0
    } else if (ptlen > *ctlen) {
1207
0
        DEBUGMSGTL(("scapi:encrypt", "bad arguments 2\n"));
1208
0
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1209
0
    }
1210
#ifdef NETSNMP_ENABLE_TESTING_CODE
1211
    {
1212
        size_t          buf_len = 128, out_len = 0;
1213
        u_char         *buf = (u_char *) malloc(buf_len);
1214
1215
        if (buf != NULL) {
1216
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1217
                                         iv, ivlen)) {
1218
                DEBUGMSGTL(("scapi", "encrypt: IV: %s\n", buf));
1219
            } else {
1220
                DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]\n", buf));
1221
            }
1222
            out_len = 0;
1223
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1224
                                         key, keylen)) {
1225
                DEBUGMSG(("scapi", "key: %s\n", buf));
1226
            } else {
1227
                DEBUGMSG(("scapi", "key: %s [TRUNCATED]\n", buf));
1228
            }
1229
            out_len = 0;
1230
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1231
                                         plaintext, 16)) {
1232
                DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf));
1233
            } else {
1234
                DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n",
1235
                            buf));
1236
            }
1237
            free(buf);
1238
        } else {
1239
            DEBUGMSGTL(("scapi",
1240
                        "encrypt: malloc fail for debug output\n"));
1241
        }
1242
    }
1243
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1244
1245
1246
    /*
1247
     * Determine privacy transform.
1248
     */
1249
0
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1250
0
    if (NULL == pai ||
1251
0
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1252
0
        DEBUGMSGTL(("scapi:encrypt",
1253
0
                    "bad arguments 3 pai %p, keylen %d ivlen %d\n",
1254
0
                    pai, keylen, ivlen));
1255
0
        if (pai)
1256
0
            DEBUGMSGTL(("scapi:encrypt", " pai: properlen %d, ivlen %d\n",
1257
0
                        pai->proper_length, pai->iv_length));
1258
1259
0
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1260
0
    }
1261
1262
0
    memset(my_iv, 0, sizeof(my_iv));
1263
1264
0
#ifndef NETSNMP_DISABLE_DES
1265
0
    if (USM_CREATE_USER_PRIV_DES == (pai->type & USM_PRIV_MASK_ALG)) {
1266
1267
        /*
1268
         * now calculate the padding needed 
1269
         */
1270
1271
0
        pad_size = pai->pad_size;
1272
0
        pad = pad_size - (ptlen % pad_size);
1273
0
        plast = (int) ptlen - (pad_size - pad);
1274
0
        if (pad == pad_size)
1275
0
            pad = 0;
1276
0
        if (ptlen + pad > *ctlen) {
1277
0
            DEBUGMSGTL(("scapi:encrypt", "not enough space\n"));
1278
0
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);    /* not enough space */
1279
0
        }
1280
0
        if (pad > 0) {              /* copy data into pad block if needed */
1281
0
            memcpy(pad_block, plaintext + plast, pad_size - pad);
1282
0
            memset(&pad_block[pad_size - pad], pad, pad);   /* filling in padblock */
1283
0
        }
1284
1285
0
        memcpy(key_struct, key, sizeof(key_struct));
1286
0
        (void) DES_key_sched(&key_struct, key_sch);
1287
1288
0
        memcpy(my_iv, iv, ivlen);
1289
        /*
1290
         * encrypt the data 
1291
         */
1292
0
        DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch,
1293
0
                         (DES_cblock *) my_iv, DES_ENCRYPT);
1294
0
        if (pad > 0) {
1295
            /*
1296
             * then encrypt the pad block 
1297
             */
1298
0
            DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size,
1299
0
                             key_sch, (DES_cblock *) my_iv, DES_ENCRYPT);
1300
0
            *ctlen = plast + pad_size;
1301
0
        } else {
1302
0
            *ctlen = plast;
1303
0
        }
1304
0
    }
1305
0
#endif
1306
0
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_AES)
1307
0
    if (USM_CREATE_USER_PRIV_AES == (pai->type & USM_PRIV_MASK_ALG)) {
1308
0
        EVP_CIPHER_CTX *ctx;
1309
0
        const EVP_CIPHER *cipher;
1310
0
        int len, rc, enclen;
1311
1312
0
        cipher = sc_get_openssl_privfn(pai->type);
1313
0
        if (NULL == cipher) {
1314
0
            DEBUGMSGTL(("scapi:encrypt", "cipher not found\n"));
1315
0
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1316
0
        }
1317
1318
0
        memcpy(my_iv, iv, ivlen);
1319
        /*
1320
         * encrypt the data 
1321
         */
1322
0
        ctx = EVP_CIPHER_CTX_new();
1323
0
        if (!ctx) {
1324
0
            DEBUGMSGTL(("scapi:encrypt", "openssl error: ctx_new\n"));
1325
0
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1326
0
        }
1327
0
        rc = EVP_EncryptInit(ctx, cipher, key, my_iv);
1328
0
        if (rc != 1) {
1329
0
            DEBUGMSGTL(("scapi:encrypt", "openssl error: init\n"));
1330
0
            EVP_CIPHER_CTX_free(ctx);
1331
0
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1332
0
        }
1333
0
        rc = EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, ptlen);
1334
0
        if (rc != 1) {
1335
0
            DEBUGMSGTL(("scapi:encrypt", "openssl error: update\n"));
1336
0
            EVP_CIPHER_CTX_free(ctx);
1337
0
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1338
0
        }
1339
0
        enclen = len;
1340
0
        rc = EVP_EncryptFinal(ctx, ciphertext + len, &len);
1341
0
        if (rc != 1) {
1342
0
            DEBUGMSGTL(("scapi:encrypt", "openssl error: final\n"));
1343
0
            EVP_CIPHER_CTX_free(ctx);
1344
0
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1345
0
        }
1346
0
        enclen += len;
1347
0
        ptlen = enclen;
1348
        /* Clean up */
1349
0
        EVP_CIPHER_CTX_free(ctx);
1350
0
        *ctlen = ptlen;
1351
0
    }
1352
0
#endif
1353
0
  sc_encrypt_quit:
1354
    /*
1355
     * clear memory just in case 
1356
     */
1357
0
    memset(my_iv, 0, sizeof(my_iv));
1358
0
    memset(pad_block, 0, sizeof(pad_block));
1359
0
#ifndef NETSNMP_DISABLE_DES
1360
0
    memset(key_struct, 0, sizeof(key_struct));
1361
#ifdef OLD_DES
1362
    memset(&key_sch, 0, sizeof(key_sch));
1363
#else
1364
0
    memset(&key_sched_store, 0, sizeof(key_sched_store));
1365
0
#endif
1366
0
#endif
1367
0
    return rval;
1368
1369
0
}                               /* end sc_encrypt() */
1370
#elif defined(NETSNMP_USE_PKCS11)
1371
{
1372
    int             rval = SNMPERR_SUCCESS, priv_type
1373
    u_char      pkcs_des_key[8];
1374
    const netsnmp_priv_alg_info *pai;
1375
1376
    DEBUGTRACE;
1377
1378
    /*
1379
     * Sanity check.
1380
     */
1381
#if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
1382
    snmp_log(LOG_ERR, "Encryption support not enabled.(1)\n");
1383
    return SNMPERR_SC_NOT_CONFIGURED;
1384
#endif
1385
1386
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
1387
        || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)) {
1388
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1389
    } else if (ptlen > *ctlen) {
1390
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1391
    }
1392
1393
    /*
1394
     * Determine privacy transform.
1395
     */
1396
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1397
    if (NULL == pai || USM_CREATE_USER_PRIV_DES != priv_type ||
1398
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1399
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
1400
    }
1401
1402
    memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
1403
    memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
1404
    rval = pkcs_encrpyt(CKM_DES_CBC, pkcs_des_key,
1405
                        sizeof(pkcs_des_key), iv, ivlen, plaintext, ptlen,
1406
                        ciphertext, ctlen);
1407
1408
  sc_encrypt_quit:
1409
    return rval;
1410
}
1411
#else
1412
{
1413
# if NETSNMP_USE_INTERNAL_MD5
1414
    {
1415
        snmp_log(LOG_ERR, "Encryption support not enabled.(3)\n");
1416
        DEBUGMSGTL(("scapi", "Encrypt function not defined.\n"));
1417
        return SNMPERR_SC_GENERAL_FAILURE;
1418
    }
1419
1420
# else
1421
    _SCAPI_NOT_CONFIGURED
1422
# endif                   /* NETSNMP_USE_INTERNAL_MD5 */
1423
}
1424
#endif                          /* */
1425
1426
1427
1428
/*******************************************************************-o-******
1429
 * sc_decrypt
1430
 *
1431
 * Parameters:
1432
 *   privtype
1433
 *  *key
1434
 *   keylen
1435
 *  *iv
1436
 *   ivlen
1437
 *  *ciphertext
1438
 *   ctlen
1439
 *  *plaintext
1440
 *  *ptlen
1441
 *      
1442
 * Returns:
1443
 *  SNMPERR_SUCCESS     Success.
1444
 *  SNMPERR_SC_NOT_CONFIGURED Encryption is not supported.
1445
 *      SNMPERR_SC_GENERAL_FAILURE      Any other error
1446
 *
1447
 *
1448
 * Decrypt ciphertext into plaintext using key and iv.
1449
 *
1450
 * ptlen contains actual number of plaintext bytes in plaintext upon
1451
 * successful return.
1452
 */
1453
int
1454
sc_decrypt(const oid * privtype, size_t privtypelen,
1455
           u_char * key, u_int keylen,
1456
           u_char * iv, u_int ivlen,
1457
           u_char * ciphertext, u_int ctlen,
1458
           u_char * plaintext, size_t * ptlen)
1459
#if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
1460
0
{
1461
1462
0
    int             rval = SNMPERR_SUCCESS;
1463
0
    u_char          my_iv[128];
1464
0
#ifndef NETSNMP_DISABLE_DES
1465
#ifdef OLD_DES
1466
    DES_key_schedule key_sch;
1467
#else
1468
0
    DES_key_schedule key_sched_store;
1469
0
    DES_key_schedule *key_sch = &key_sched_store;
1470
0
#endif
1471
0
    DES_cblock      key_struct;
1472
0
#endif
1473
0
    const netsnmp_priv_alg_info *pai = NULL;
1474
1475
0
    DEBUGTRACE;
1476
1477
0
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
1478
0
        || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)) {
1479
0
        DEBUGMSGTL(("scapi", "decrypt: arg sanity checks failed\n"));
1480
0
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1481
0
    }
1482
#ifdef NETSNMP_ENABLE_TESTING_CODE
1483
    {
1484
        size_t          buf_len = 128, out_len = 0;
1485
        u_char         *buf = (u_char *) malloc(buf_len);
1486
1487
        if (buf != NULL) {
1488
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1489
                                         iv, ivlen)) {
1490
                DEBUGMSGTL(("scapi", "decrypt: IV: %s\n", buf));
1491
            } else {
1492
                DEBUGMSGTL(("scapi", "decrypt: IV: %s [TRUNCATED]\n", buf));
1493
            }
1494
            out_len = 0;
1495
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
1496
                                         key, keylen)) {
1497
                DEBUGMSG(("scapi", "key: %s\n", buf));
1498
            } else {
1499
                DEBUGMSG(("scapi", "key: %s [TRUNCATED]\n", buf));
1500
            }
1501
            free(buf);
1502
        } else {
1503
            DEBUGMSGTL(("scapi",
1504
                        "decrypt: malloc fail for debug output\n"));
1505
        }
1506
    }
1507
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1508
1509
    /*
1510
     * Determine privacy transform.
1511
     */
1512
0
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1513
0
    if (NULL == pai ||
1514
0
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1515
0
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1516
0
    }
1517
1518
0
    memset(my_iv, 0, sizeof(my_iv));
1519
0
#ifndef NETSNMP_DISABLE_DES
1520
0
    if (USM_CREATE_USER_PRIV_DES == (pai->type & USM_PRIV_MASK_ALG)) {
1521
0
        memcpy(key_struct, key, sizeof(key_struct));
1522
0
        (void) DES_key_sched(&key_struct, key_sch);
1523
1524
0
        memcpy(my_iv, iv, ivlen);
1525
0
        DES_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch,
1526
0
                        (DES_cblock *) my_iv, DES_DECRYPT);
1527
0
        *ptlen = ctlen;
1528
0
    }
1529
0
#endif
1530
0
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_AES)
1531
0
    if (USM_CREATE_USER_PRIV_AES == (pai->type & USM_PRIV_MASK_ALG)) {
1532
0
        EVP_CIPHER_CTX *ctx;
1533
0
        const EVP_CIPHER *cipher;
1534
0
        int len, rc;
1535
1536
0
        cipher = sc_get_openssl_privfn(pai->type);
1537
0
        if (NULL == cipher)
1538
0
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1539
1540
0
        memcpy(my_iv, iv, ivlen);
1541
        /*
1542
         * decrypt the data
1543
         */
1544
0
        ctx = EVP_CIPHER_CTX_new();
1545
0
        if (!ctx) {
1546
0
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1547
0
        }
1548
0
        rc = EVP_DecryptInit(ctx, cipher, key, my_iv);
1549
0
        if (rc != 1) {
1550
0
            EVP_CIPHER_CTX_free(ctx);
1551
0
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1552
0
        }
1553
0
        rc = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ctlen);
1554
0
        if (rc != 1) {
1555
0
            EVP_CIPHER_CTX_free(ctx);
1556
0
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1557
0
        }
1558
0
        rc = EVP_DecryptFinal(ctx, plaintext + len, &len);
1559
0
        if (rc != 1) {
1560
0
            EVP_CIPHER_CTX_free(ctx);
1561
0
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1562
0
        }
1563
        /* Clean up */
1564
0
        EVP_CIPHER_CTX_free(ctx);
1565
0
        *ptlen = ctlen;
1566
0
    }
1567
0
#endif
1568
1569
    /*
1570
     * exit cond 
1571
     */
1572
0
  sc_decrypt_quit:
1573
0
#ifndef NETSNMP_DISABLE_DES
1574
#ifdef OLD_DES
1575
    memset(&key_sch, 0, sizeof(key_sch));
1576
#else
1577
0
    memset(&key_sched_store, 0, sizeof(key_sched_store));
1578
0
#endif
1579
0
    memset(key_struct, 0, sizeof(key_struct));
1580
0
#endif
1581
0
    memset(my_iv, 0, sizeof(my_iv));
1582
0
    return rval;
1583
0
}        /* USE OPEN_SSL */
1584
#elif defined(NETSNMP_USE_PKCS11)        /* USE PKCS */
1585
{
1586
    int             rval = SNMPERR_SUCCESS;
1587
    u_char      pkcs_des_key[8];
1588
    const netsnmp_priv_alg_info *pai;
1589
1590
    DEBUGTRACE;
1591
1592
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
1593
        || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)) {
1594
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1595
    }
1596
1597
    /*
1598
     * Determine privacy transform.
1599
     */
1600
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
1601
    if (NULL == pai || USM_CREATE_USER_PRIV_DES != priv_type ||
1602
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
1603
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
1604
    }
1605
1606
    memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
1607
    memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
1608
    rval = pkcs_decrpyt(CKM_DES_CBC, pkcs_des_key, 
1609
                        sizeof(pkcs_des_key), iv, ivlen, ciphertext,
1610
                        ctlen, plaintext, ptlen);
1611
    *ptlen = ctlen;
1612
1613
  sc_decrypt_quit:
1614
    return rval;
1615
}       /* USE PKCS */
1616
#else
1617
{
1618
#if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
1619
    snmp_log(LOG_ERR, "Encryption support not enabled.(4)\n");
1620
    return SNMPERR_SC_NOT_CONFIGURED;
1621
#else
1622
# if NETSNMP_USE_INTERNAL_MD5
1623
    {
1624
        DEBUGMSGTL(("scapi", "Decryption function not defined.\n"));
1625
        return SNMPERR_SC_GENERAL_FAILURE;
1626
    }
1627
1628
# else
1629
    _SCAPI_NOT_CONFIGURED
1630
# endif                   /* NETSNMP_USE_INTERNAL_MD5 */
1631
#endif                          /*  */
1632
}
1633
#endif                          /* NETSNMP_USE_OPENSSL */
1634
1635
#ifdef NETSNMP_USE_INTERNAL_CRYPTO
1636
1637
/* These functions are basically copies of the MDSign() routine in
1638
   md5.c modified to be used with the OpenSSL hashing functions.  The
1639
   copyright below is from the md5.c file that these functions were
1640
   taken from: */
1641
1642
/*
1643
 * ** **************************************************************************
1644
 * ** md5.c -- Implementation of MD5 Message Digest Algorithm                 **
1645
 * ** Updated: 2/16/90 by Ronald L. Rivest                                    **
1646
 * ** (C) 1990 RSA Data Security, Inc.                                        **
1647
 * ** **************************************************************************
1648
 */
1649
1650
/*
1651
 * MD5_hmac(data, len, MD5): do a checksum on an arbitrary amount
1652
 * of data, and prepended with a secret in the standard fashion 
1653
 */
1654
static int
1655
MD5_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
1656
         const u_char * secret, size_t secretlen)
1657
{
1658
#define MD5_HASHKEYLEN 64
1659
#define MD5_SECRETKEYLEN 16
1660
1661
    MD5_CTX         cmd5;
1662
    u_char          K1[MD5_HASHKEYLEN];
1663
    u_char          K2[MD5_HASHKEYLEN];
1664
    u_char          extendedAuthKey[MD5_HASHKEYLEN];
1665
    u_char          buf[MD5_HASHKEYLEN];
1666
    size_t          i;
1667
    const u_char   *cp;
1668
    u_char         *newdata = NULL;
1669
    int             rc = 0;
1670
1671
    DEBUGTRACE;
1672
1673
    /*
1674
     * memset(K1,0,MD5_HASHKEYLEN);
1675
     * memset(K2,0,MD5_HASHKEYLEN);
1676
     * memset(buf,0,MD5_HASHKEYLEN);
1677
     * memset(extendedAuthKey,0,MD5_HASHKEYLEN);
1678
     */
1679
1680
    if (secretlen != MD5_SECRETKEYLEN || secret == NULL ||
1681
        mac == NULL || data == NULL ||
1682
        len <= 0 || maclen <= 0) {
1683
        /*
1684
         * DEBUGMSGTL(("md5","MD5 signing not properly initialized")); 
1685
         */
1686
        return -1;
1687
    }
1688
1689
    memset(extendedAuthKey, 0, MD5_HASHKEYLEN);
1690
    memcpy(extendedAuthKey, secret, secretlen);
1691
    for (i = 0; i < MD5_HASHKEYLEN; i++) {
1692
        K1[i] = extendedAuthKey[i] ^ 0x36;
1693
        K2[i] = extendedAuthKey[i] ^ 0x5c;
1694
    }
1695
1696
    MD5_Init(&cmd5);
1697
    rc = !MD5_Update(&cmd5, K1, MD5_HASHKEYLEN);
1698
    if (rc)
1699
        goto update_end;
1700
1701
    i = len;
1702
    if (((uintptr_t) data) % sizeof(long) != 0) {
1703
        /*
1704
         * this relies on the ability to use integer math and thus we
1705
         * must rely on data that aligns on 32-bit-word-boundaries 
1706
         */
1707
        newdata = netsnmp_memdup(data, len);
1708
        cp = newdata;
1709
    } else {
1710
        cp = data;
1711
    }
1712
1713
    while (i >= 64) {
1714
        rc = !MD5_Update(&cmd5, cp, 64);
1715
        if (rc)
1716
            goto update_end;
1717
        cp += 64;
1718
        i -= 64;
1719
    }
1720
1721
    rc = !MD5_Update(&cmd5, cp, i);
1722
    if (rc)
1723
        goto update_end;
1724
1725
    memset(buf, 0, MD5_HASHKEYLEN);
1726
    MD5_Final(buf, &cmd5);
1727
1728
    MD5_Init(&cmd5);
1729
    rc = !MD5_Update(&cmd5, K2, MD5_HASHKEYLEN);
1730
    if (rc)
1731
        goto update_end;
1732
    rc = !MD5_Update(&cmd5, buf, MD5_SECRETKEYLEN);
1733
    if (rc)
1734
        goto update_end;
1735
1736
    /*
1737
     * copy the sign checksum to the outgoing pointer 
1738
     */
1739
    MD5_Final(buf, &cmd5);
1740
    memcpy(mac, buf, maclen);
1741
1742
  update_end:
1743
    memset(buf, 0, MD5_HASHKEYLEN);
1744
    memset(K1, 0, MD5_HASHKEYLEN);
1745
    memset(K2, 0, MD5_HASHKEYLEN);
1746
    memset(extendedAuthKey, 0, MD5_HASHKEYLEN);
1747
    memset(&cmd5, 0, sizeof(cmd5));
1748
1749
    if (newdata)
1750
        free(newdata);
1751
    return rc;
1752
}
1753
1754
static int
1755
SHA1_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
1756
          const u_char * secret, size_t secretlen)
1757
{
1758
#define SHA1_HASHKEYLEN   64
1759
#define SHA1_SECRETKEYLEN 20
1760
1761
    SHA_CTX         csha1;
1762
    u_char          K1[SHA1_HASHKEYLEN];
1763
    u_char          K2[SHA1_HASHKEYLEN];
1764
    u_char          extendedAuthKey[SHA1_HASHKEYLEN];
1765
    u_char          buf[SHA1_HASHKEYLEN];
1766
    size_t          i;
1767
    const u_char   *cp;
1768
    u_char         *newdata = NULL;
1769
    int             rc = 0;
1770
1771
    DEBUGTRACE;
1772
1773
    /*
1774
     * memset(K1,0,SHA1_HASHKEYLEN);
1775
     * memset(K2,0,SHA1_HASHKEYLEN);
1776
     * memset(buf,0,SHA1_HASHKEYLEN);
1777
     * memset(extendedAuthKey,0,SHA1_HASHKEYLEN);
1778
     */
1779
1780
    if (secretlen != SHA1_SECRETKEYLEN || secret == NULL ||
1781
        mac == NULL || data == NULL ||
1782
        len <= 0 || maclen <= 0) {
1783
        /*
1784
         * DEBUGMSGTL(("sha1","SHA1 signing not properly initialized")); 
1785
         */
1786
        return -1;
1787
    }
1788
1789
    memset(extendedAuthKey, 0, SHA1_HASHKEYLEN);
1790
    memcpy(extendedAuthKey, secret, secretlen);
1791
    for (i = 0; i < SHA1_HASHKEYLEN; i++) {
1792
        K1[i] = extendedAuthKey[i] ^ 0x36;
1793
        K2[i] = extendedAuthKey[i] ^ 0x5c;
1794
    }
1795
1796
    SHA1_Init(&csha1);
1797
    rc = !SHA1_Update(&csha1, K1, SHA1_HASHKEYLEN);
1798
    if (rc)
1799
        goto update_end;
1800
1801
    i = len;
1802
    if (((uintptr_t) data) % sizeof(long) != 0) {
1803
        /*
1804
         * this relies on the ability to use integer math and thus we
1805
         * must rely on data that aligns on 32-bit-word-boundaries 
1806
         */
1807
        newdata = netsnmp_memdup(data, len);
1808
        cp = newdata;
1809
    } else {
1810
        cp = data;
1811
    }
1812
1813
    while (i >= 64) {
1814
        rc = !SHA1_Update(&csha1, cp, 64);
1815
        if (rc)
1816
            goto update_end;
1817
        cp += 64;
1818
        i -= 64;
1819
    }
1820
1821
    rc = !SHA1_Update(&csha1, cp, i);
1822
    if (rc)
1823
        goto update_end;
1824
1825
    memset(buf, 0, SHA1_HASHKEYLEN);
1826
    SHA1_Final(buf, &csha1);
1827
1828
    SHA1_Init(&csha1);
1829
    rc = !SHA1_Update(&csha1, K2, SHA1_HASHKEYLEN);
1830
    if (rc)
1831
        goto update_end;
1832
    rc = !SHA1_Update(&csha1, buf, SHA1_SECRETKEYLEN);
1833
    if (rc)
1834
        goto update_end;
1835
1836
    /*
1837
     * copy the sign checksum to the outgoing pointer 
1838
     */
1839
    SHA1_Final(buf, &csha1);
1840
    memcpy(mac, buf, maclen);
1841
1842
  update_end:
1843
    memset(buf, 0, SHA1_HASHKEYLEN);
1844
    memset(K1, 0, SHA1_HASHKEYLEN);
1845
    memset(K2, 0, SHA1_HASHKEYLEN);
1846
    memset(extendedAuthKey, 0, SHA1_HASHKEYLEN);
1847
    memset(&csha1, 0, sizeof(csha1));
1848
1849
    if (newdata)
1850
        free(newdata);
1851
    return rc;
1852
}
1853
#endif /* NETSNMP_USE_INTERNAL_CRYPTO */
1854
#endif /*  NETSNMP_FEATURE_REMOVE_USM_SCAPI  */