Coverage Report

Created: 2026-10-17 06:54

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