Coverage Report

Created: 2026-09-04 07:13

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