~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to snmplib/scapi.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
12
/*
 
13
 * scapi.c
 
14
 *
 
15
 */
 
16
 
 
17
#include <net-snmp/net-snmp-config.h>
 
18
 
 
19
#include <sys/types.h>
 
20
#if HAVE_WINSOCK_H
 
21
#include <winsock.h>
 
22
#endif
 
23
#ifdef HAVE_STDLIB_H
 
24
#include <stdlib.h>
 
25
#endif
 
26
#if HAVE_STRING_H
 
27
#include <string.h>
 
28
#else
 
29
#include <strings.h>
 
30
#endif
 
31
#if TIME_WITH_SYS_TIME
 
32
# ifdef WIN32
 
33
#  include <sys/timeb.h>
 
34
# else
 
35
#  include <sys/time.h>
 
36
# endif
 
37
# include <time.h>
 
38
#else
 
39
# if HAVE_SYS_TIME_H
 
40
#  include <sys/time.h>
 
41
# else
 
42
#  include <time.h>
 
43
# endif
 
44
#endif
 
45
#ifdef HAVE_NETINET_IN_H
 
46
#include <netinet/in.h>
 
47
#endif
 
48
 
 
49
#if HAVE_DMALLOC_H
 
50
#include <dmalloc.h>
 
51
#endif
 
52
 
 
53
#include <net-snmp/types.h>
 
54
#include <net-snmp/output_api.h>
 
55
#include <net-snmp/utilities.h>
 
56
 
 
57
#ifdef USE_INTERNAL_MD5
 
58
#include <net-snmp/library/md5.h>
 
59
#endif
 
60
#include <net-snmp/library/snmp_api.h>
 
61
#include <net-snmp/library/callback.h>
 
62
#include <net-snmp/library/snmp_secmod.h>
 
63
#include <net-snmp/library/snmpusm.h>
 
64
#include <net-snmp/library/keytools.h>
 
65
#include <net-snmp/library/scapi.h>
 
66
#include <net-snmp/library/mib.h>
 
67
#include <net-snmp/library/transform_oids.h>
 
68
 
 
69
#ifdef USE_OPENSSL
 
70
#include <openssl/hmac.h>
 
71
#include <openssl/evp.h>
 
72
#include <openssl/rand.h>
 
73
#include <openssl/des.h>
 
74
#ifdef HAVE_AES
 
75
#include <openssl/aes.h>
 
76
#endif
 
77
 
 
78
#ifdef STRUCT_DES_KS_STRUCT_HAS_WEAK_KEY
 
79
/* these are older names for newer structures that exist in openssl .9.7 */
 
80
#define DES_key_schedule    des_key_schedule 
 
81
#define DES_cblock          des_cblock 
 
82
#define DES_key_sched       des_key_sched 
 
83
#define DES_ncbc_encrypt    des_ncbc_encrypt
 
84
#define DES_cbc_encrypt    des_cbc_encrypt
 
85
#define OLD_DES
 
86
#endif
 
87
 
 
88
#endif /* HAVE_OPENSSL */
 
89
 
 
90
#ifdef USE_PKCS
 
91
#include <security/cryptoki.h>
 
92
#endif
 
93
 
 
94
#ifdef QUITFUN
 
95
#undef QUITFUN
 
96
#define QUITFUN(e, l)                                   \
 
97
        if (e != SNMPERR_SUCCESS) {                     \
 
98
                rval = SNMPERR_SC_GENERAL_FAILURE;      \
 
99
                goto l ;                                \
 
100
        }
 
101
#endif
 
102
 
 
103
 
 
104
/*
 
105
 * sc_get_properlength(oid *hashtype, u_int hashtype_len):
 
106
 * 
 
107
 * Given a hashing type ("hashtype" and its length hashtype_len), return
 
108
 * the length of the hash result.
 
109
 * 
 
110
 * Returns either the length or SNMPERR_GENERR for an unknown hashing type.
 
111
 */
 
112
int
 
113
sc_get_properlength(const oid * hashtype, u_int hashtype_len)
 
114
{
 
115
    DEBUGTRACE;
 
116
    /*
 
117
     * Determine transform type hash length.
 
118
     */
 
119
    if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
 
120
        return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5);
 
121
    } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
 
122
        return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
 
123
    }
 
124
    return SNMPERR_GENERR;
 
125
}
 
126
 
 
127
 
 
128
/*******************************************************************-o-******
 
129
 * sc_init
 
130
 *
 
131
 * Returns:
 
132
 *      SNMPERR_SUCCESS                 Success.
 
133
 */
 
134
int
 
135
sc_init(void)
 
136
{
 
137
    int             rval = SNMPERR_SUCCESS;
 
138
 
 
139
#ifndef USE_OPENSSL
 
140
#ifdef USE_INTERNAL_MD5
 
141
    struct timeval  tv;
 
142
 
 
143
    DEBUGTRACE;
 
144
 
 
145
    gettimeofday(&tv, (struct timezone *) 0);
 
146
 
 
147
    srandom(tv.tv_sec ^ tv.tv_usec);
 
148
#elif USE_PKCS
 
149
    DEBUGTRACE;
 
150
    rval = pkcs_init();
 
151
#else
 
152
    rval = SNMPERR_SC_NOT_CONFIGURED;
 
153
#endif                           /* USE_INTERNAL_MD5 */
 
154
    /*
 
155
     * XXX ogud: The only reason to do anything here with openssl is to 
 
156
     * * XXX ogud: seed random number generator 
 
157
     */
 
158
#endif                          /* ifndef USE_OPENSSL */
 
159
    return rval;
 
160
}                               /* end sc_init() */
 
161
 
 
162
/*******************************************************************-o-******
 
163
 * sc_random
 
164
 *
 
165
 * Parameters:
 
166
 *      *buf            Pre-allocated buffer.
 
167
 *      *buflen         Size of buffer.
 
168
 *      
 
169
 * Returns:
 
170
 *      SNMPERR_SUCCESS                 Success.
 
171
 */
 
172
int
 
173
sc_random(u_char * buf, size_t * buflen)
 
174
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
 
175
{
 
176
    int             rval = SNMPERR_SUCCESS;
 
177
#ifdef USE_INTERNAL_MD5
 
178
    int             i;
 
179
    int             rndval;
 
180
    u_char         *ucp = buf;
 
181
#endif
 
182
 
 
183
    DEBUGTRACE;
 
184
 
 
185
#ifdef USE_OPENSSL
 
186
    RAND_bytes(buf, *buflen);   /* will never fail */
 
187
#elif USE_PKCS                  /* USE_PKCS */
 
188
    pkcs_random(buf, *buflen);
 
189
#else                           /* USE_INTERNAL_MD5 */
 
190
    /*
 
191
     * fill the buffer with random integers.  Note that random()
 
192
     * is defined in config.h and may not be truly the random()
 
193
     * system call if something better existed 
 
194
     */
 
195
    rval = *buflen - *buflen % sizeof(rndval);
 
196
    for (i = 0; i < rval; i += sizeof(rndval)) {
 
197
        rndval = random();
 
198
        memcpy(ucp, &rndval, sizeof(rndval));
 
199
        ucp += sizeof(rndval);
 
200
    }
 
201
 
 
202
    rndval = random();
 
203
    memcpy(ucp, &rndval, *buflen % sizeof(rndval));
 
204
 
 
205
    rval = SNMPERR_SUCCESS;
 
206
#endif                          /* USE_OPENSSL */
 
207
    return rval;
 
208
 
 
209
}                               /* end sc_random() */
 
210
 
 
211
#else
 
212
_SCAPI_NOT_CONFIGURED
 
213
#endif                          /*  */
 
214
/*******************************************************************-o-******
 
215
 * sc_generate_keyed_hash
 
216
 *
 
217
 * Parameters:
 
218
 *       authtype       Type of authentication transform.
 
219
 *       authtypelen
 
220
 *      *key            Pointer to key (Kul) to use in keyed hash.
 
221
 *       keylen         Length of key in bytes.
 
222
 *      *message        Pointer to the message to hash.
 
223
 *       msglen         Length of the message.
 
224
 *      *MAC            Will be returned with allocated bytes containg hash.
 
225
 *      *maclen         Length of the hash buffer in bytes; also indicates
 
226
 *                              whether the MAC should be truncated.
 
227
 *      
 
228
 * Returns:
 
229
 *      SNMPERR_SUCCESS                 Success.
 
230
 *      SNMPERR_GENERR                  All errs
 
231
 *
 
232
 *
 
233
 * A hash of the first msglen bytes of message using a keyed hash defined
 
234
 * by authtype is created and stored in MAC.  MAC is ASSUMED to be a buffer
 
235
 * of at least maclen bytes.  If the length of the hash is greater than
 
236
 * maclen, it is truncated to fit the buffer.  If the length of the hash is
 
237
 * less than maclen, maclen set to the number of hash bytes generated.
 
238
 *
 
239
 * ASSUMED that the number of hash bits is a multiple of 8.
 
240
 */
 
241
int
 
242
sc_generate_keyed_hash(const oid * authtype, size_t authtypelen,
 
243
                       u_char * key, u_int keylen,
 
244
                       u_char * message, u_int msglen,
 
245
                       u_char * MAC, size_t * maclen)
 
246
#if  defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
 
247
{
 
248
    int             rval = SNMPERR_SUCCESS;
 
249
    int             properlength;
 
250
 
 
251
    u_char          buf[SNMP_MAXBUF_SMALL];
 
252
#if  defined(USE_OPENSSL) || defined(USE_PKCS)
 
253
    size_t             buf_len = sizeof(buf);
 
254
#endif
 
255
 
 
256
    DEBUGTRACE;
 
257
 
 
258
#ifdef SNMP_TESTING_CODE
 
259
    {
 
260
        int             i;
 
261
        DEBUGMSG(("sc_generate_keyed_hash",
 
262
                  "sc_generate_keyed_hash(): key=0x"));
 
263
        for (i = 0; i < keylen; i++)
 
264
            DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff));
 
265
        DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen));
 
266
    }
 
267
#endif                          /* SNMP_TESTING_CODE */
 
268
 
 
269
    /*
 
270
     * Sanity check.
 
271
     */
 
272
    if (!authtype || !key || !message || !MAC || !maclen
 
273
        || (keylen <= 0) || (msglen <= 0) || (*maclen <= 0)
 
274
        || (authtypelen != USM_LENGTH_OID_TRANSFORM)) {
 
275
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
 
276
    }
 
277
 
 
278
    properlength = sc_get_properlength(authtype, authtypelen);
 
279
    if (properlength == SNMPERR_GENERR)
 
280
        return properlength;
 
281
 
 
282
    if (((int) keylen < properlength)) {
 
283
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
 
284
    }
 
285
#ifdef USE_OPENSSL
 
286
    /*
 
287
     * Determine transform type.
 
288
     */
 
289
    if (ISTRANSFORM(authtype, HMACMD5Auth))
 
290
        HMAC(EVP_md5(), key, keylen, message, msglen, buf, &buf_len);
 
291
    else if (ISTRANSFORM(authtype, HMACSHA1Auth))
 
292
        HMAC(EVP_sha1(), key, keylen, message, msglen, buf, &buf_len);
 
293
    else {
 
294
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
 
295
    }
 
296
    if ((int)buf_len != properlength) {
 
297
        QUITFUN(rval, sc_generate_keyed_hash_quit);
 
298
    }
 
299
    if ((int)*maclen > buf_len)
 
300
        *maclen = buf_len;
 
301
    memcpy(MAC, buf, *maclen);
 
302
 
 
303
#elif USE_PKCS                    /* USE_PKCS */
 
304
 
 
305
    if (ISTRANSFORM(authtype, HMACMD5Auth)) {
 
306
        if (pkcs_sign(CKM_MD5_HMAC,key, keylen, message,
 
307
                        msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
 
308
            QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
 
309
        }
 
310
    } else if (ISTRANSFORM(authtype, HMACSHA1Auth)) {
 
311
        if (pkcs_sign(CKM_SHA_1_HMAC,key, keylen, message,
 
312
                        msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
 
313
            QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
 
314
        }
 
315
    } else {
 
316
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
 
317
    }
 
318
 
 
319
    if (buf_len != properlength) {
 
320
        QUITFUN(rval, sc_generate_keyed_hash_quit);
 
321
    }
 
322
    if (*maclen > buf_len)
 
323
        *maclen = buf_len;
 
324
    memcpy(MAC, buf, *maclen);
 
325
 
 
326
#else                            /* USE_INTERNAL_MD5 */
 
327
    if ((int) *maclen > properlength)
 
328
        *maclen = properlength;
 
329
    if (MDsign(message, msglen, MAC, *maclen, key, keylen)) {
 
330
        rval = SNMPERR_GENERR;
 
331
        goto sc_generate_keyed_hash_quit;
 
332
    }
 
333
#endif                          /* USE_OPENSSL */
 
334
 
 
335
#ifdef SNMP_TESTING_CODE
 
336
    {
 
337
        char           *s;
 
338
        int             len = binary_to_hex(MAC, *maclen, &s);
 
339
 
 
340
        DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s));
 
341
        SNMP_ZERO(s, len);
 
342
        SNMP_FREE(s);
 
343
    }
 
344
#endif                          /* SNMP_TESTING_CODE */
 
345
 
 
346
  sc_generate_keyed_hash_quit:
 
347
    SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
 
348
    return rval;
 
349
}                               /* end sc_generate_keyed_hash() */
 
350
 
 
351
#else
 
352
                _SCAPI_NOT_CONFIGURED
 
353
#endif                          /* */
 
354
/*
 
355
 * sc_hash(): a generic wrapper around whatever hashing package we are using.
 
356
 * 
 
357
 * IN:
 
358
 * hashtype    - oid pointer to a hash type
 
359
 * hashtypelen - length of oid pointer
 
360
 * buf         - u_char buffer to be hashed
 
361
 * buf_len     - integer length of buf data
 
362
 * MAC_len     - length of the passed MAC buffer size.
 
363
 * 
 
364
 * OUT:    
 
365
 * MAC         - pre-malloced space to store hash output.
 
366
 * MAC_len     - length of MAC output to the MAC buffer.
 
367
 * 
 
368
 * Returns:
 
369
 * SNMPERR_SUCCESS              Success.
 
370
 * SNMP_SC_GENERAL_FAILURE      Any error.
 
371
 */
 
372
int
 
373
sc_hash(const oid * hashtype, size_t hashtypelen, u_char * buf,
 
374
        size_t buf_len, u_char * MAC, size_t * MAC_len)
 
375
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
 
376
{
 
377
#if defined(USE_OPENSSL) || defined(USE_PKCS)
 
378
    int             rval = SNMPERR_SUCCESS;
 
379
#endif
 
380
 
 
381
#ifdef USE_OPENSSL
 
382
    const EVP_MD         *hashfn;
 
383
    EVP_MD_CTX     ctx, *cptr;
 
384
#endif
 
385
 
 
386
    DEBUGTRACE;
 
387
 
 
388
    if (hashtype == NULL || hashtypelen < 0 || buf == NULL ||
 
389
        buf_len < 0 || MAC == NULL || MAC_len == NULL ||
 
390
        (int) (*MAC_len) < sc_get_properlength(hashtype, hashtypelen))
 
391
        return (SNMPERR_GENERR);
 
392
 
 
393
#ifdef USE_OPENSSL
 
394
    /*
 
395
     * Determine transform type.
 
396
     */
 
397
    if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
 
398
        hashfn = (const EVP_MD *) EVP_md5();
 
399
    } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
 
400
        hashfn = (const EVP_MD *) EVP_sha1();
 
401
    } else {
 
402
        return (SNMPERR_GENERR);
 
403
    }
 
404
 
 
405
/** initialize the pointer */
 
406
    memset(&ctx, 0, sizeof(ctx));
 
407
    cptr = &ctx;
 
408
#if defined(OLD_DES)
 
409
    EVP_DigestInit(cptr, hashfn);
 
410
#else /* !OLD_DES */
 
411
    /* this is needed if the runtime library is different than the compiled
 
412
       library since the openssl versions are very different. */
 
413
    if (SSLeay() < 0x907000) {
 
414
        /* the old version of the struct was bigger and thus more
 
415
           memory is needed. should be 152, but we use 256 for safety. */
 
416
        cptr = malloc(256);
 
417
        EVP_DigestInit(cptr, hashfn);
 
418
    } else {
 
419
        EVP_MD_CTX_init(cptr);
 
420
        EVP_DigestInit(cptr, hashfn);
 
421
    }
 
422
#endif
 
423
 
 
424
/** pass the data */
 
425
    EVP_DigestUpdate(cptr, buf, buf_len);
 
426
 
 
427
/** do the final pass */
 
428
#if defined(OLD_DES)
 
429
    EVP_DigestFinal(cptr, MAC, MAC_len);
 
430
#else /* !OLD_DES */
 
431
    if (SSLeay() < 0x907000) {
 
432
        EVP_DigestFinal(cptr, MAC, MAC_len);
 
433
        free(cptr);
 
434
    } else {
 
435
        EVP_DigestFinal_ex(cptr, MAC, MAC_len);
 
436
        EVP_MD_CTX_cleanup(cptr);
 
437
    }
 
438
#endif                          /* OLD_DES */
 
439
    return (rval);
 
440
#elif USE_PKCS                  /* USE_PKCS */
 
441
 
 
442
    if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
 
443
        rval = pkcs_digest(CKM_MD5, buf, buf_len, MAC, MAC_len);
 
444
    } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
 
445
        rval = pkcs_digest(CKM_SHA_1, buf, buf_len, MAC, MAC_len);
 
446
    } else {
 
447
        return (SNMPERR_GENERR);
 
448
    }
 
449
 
 
450
     return (rval);
 
451
 
 
452
#else                           /* USE_INTERNAL_MD5 */
 
453
 
 
454
    if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
 
455
        return SNMPERR_GENERR;
 
456
    }
 
457
    if (*MAC_len > 16)
 
458
        *MAC_len = 16;
 
459
    return SNMPERR_SUCCESS;
 
460
 
 
461
#endif                          /* USE_OPENSSL */
 
462
}
 
463
#else                           /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */
 
464
_SCAPI_NOT_CONFIGURED
 
465
#endif                          /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */
 
466
/*******************************************************************-o-******
 
467
 * sc_check_keyed_hash
 
468
 *
 
469
 * Parameters:
 
470
 *       authtype       Transform type of authentication hash.
 
471
 *      *key            Key bits in a string of bytes.
 
472
 *       keylen         Length of key in bytes.
 
473
 *      *message        Message for which to check the hash.
 
474
 *       msglen         Length of message.
 
475
 *      *MAC            Given hash.
 
476
 *       maclen         Length of given hash; indicates truncation if it is
 
477
 *                              shorter than the normal size of output for
 
478
 *                              given hash transform.
 
479
 * Returns:
 
480
 *      SNMPERR_SUCCESS         Success.
 
481
 *      SNMP_SC_GENERAL_FAILURE Any error
 
482
 *
 
483
 *
 
484
 * Check the hash given in MAC against the hash of message.  If the length
 
485
 * of MAC is less than the length of the transform hash output, only maclen
 
486
 * bytes are compared.  The length of MAC cannot be greater than the
 
487
 * length of the hash transform output.
 
488
 */
 
489
int
 
490
sc_check_keyed_hash(const oid * authtype, size_t authtypelen,
 
491
                    u_char * key, u_int keylen,
 
492
                    u_char * message, u_int msglen,
 
493
                    u_char * MAC, u_int maclen)
 
494
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) || defined(USE_PKCS)
 
495
{
 
496
    int             rval = SNMPERR_SUCCESS;
 
497
    size_t          buf_len = SNMP_MAXBUF_SMALL;
 
498
 
 
499
    u_char          buf[SNMP_MAXBUF_SMALL];
 
500
 
 
501
    DEBUGTRACE;
 
502
 
 
503
#ifdef SNMP_TESTING_CODE
 
504
    {
 
505
        int             i;
 
506
        DEBUGMSG(("scapi", "sc_check_keyed_hash():    key=0x"));
 
507
        for (i = 0; i < keylen; i++)
 
508
            DEBUGMSG(("scapi", "%02x", key[i] & 0xff));
 
509
        DEBUGMSG(("scapi", " (%d)\n", keylen));
 
510
    }
 
511
#endif                          /* SNMP_TESTING_CODE */
 
512
 
 
513
    /*
 
514
     * Sanity check.
 
515
     */
 
516
    if (!authtype || !key || !message || !MAC
 
517
        || (keylen <= 0) || (msglen <= 0) || (maclen <= 0)
 
518
        || (authtypelen != USM_LENGTH_OID_TRANSFORM)) {
 
519
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
 
520
    }
 
521
 
 
522
 
 
523
    /*
 
524
     * Generate a full hash of the message, then compare
 
525
     * the result with the given MAC which may shorter than
 
526
     * the full hash length.
 
527
     */
 
528
    rval = sc_generate_keyed_hash(authtype, authtypelen,
 
529
                                  key, keylen,
 
530
                                  message, msglen, buf, &buf_len);
 
531
    QUITFUN(rval, sc_check_keyed_hash_quit);
 
532
 
 
533
    if (maclen > msglen) {
 
534
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
 
535
 
 
536
    } else if (memcmp(buf, MAC, maclen) != 0) {
 
537
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
 
538
    }
 
539
 
 
540
 
 
541
  sc_check_keyed_hash_quit:
 
542
    SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
 
543
 
 
544
    return rval;
 
545
 
 
546
}                               /* end sc_check_keyed_hash() */
 
547
 
 
548
#else
 
549
_SCAPI_NOT_CONFIGURED
 
550
#endif                          /* USE_INTERNAL_MD5 */
 
551
/*******************************************************************-o-******
 
552
 * sc_encrypt
 
553
 *
 
554
 * Parameters:
 
555
 *       privtype       Type of privacy cryptographic transform.
 
556
 *      *key            Key bits for crypting.
 
557
 *       keylen         Length of key (buffer) in bytes.
 
558
 *      *iv             IV bits for crypting.
 
559
 *       ivlen          Length of iv (buffer) in bytes.
 
560
 *      *plaintext      Plaintext to crypt.
 
561
 *       ptlen          Length of plaintext.
 
562
 *      *ciphertext     Ciphertext to crypt.
 
563
 *      *ctlen          Length of ciphertext.
 
564
 *      
 
565
 * Returns:
 
566
 *      SNMPERR_SUCCESS                 Success.
 
567
 *      SNMPERR_SC_NOT_CONFIGURED       Encryption is not supported.
 
568
 *      SNMPERR_SC_GENERAL_FAILURE      Any other error
 
569
 *
 
570
 *
 
571
 * Encrypt plaintext into ciphertext using key and iv.
 
572
 *
 
573
 * ctlen contains actual number of crypted bytes in ciphertext upon
 
574
 * successful return.
 
575
 */
 
576
int
 
577
sc_encrypt(const oid * privtype, size_t privtypelen,
 
578
           u_char * key, u_int keylen,
 
579
           u_char * iv, u_int ivlen,
 
580
           u_char * plaintext, u_int ptlen,
 
581
           u_char * ciphertext, size_t * ctlen)
 
582
#if defined(USE_OPENSSL)
 
583
{
 
584
    int             rval = SNMPERR_SUCCESS;
 
585
    u_int           properlength, properlength_iv;
 
586
    u_char          pad_block[128];      /* bigger than anything I need */
 
587
    u_char          my_iv[128];  /* ditto */
 
588
    int             pad, plast, pad_size = 0;
 
589
#ifdef OLD_DES
 
590
    DES_key_schedule key_sch;
 
591
#else
 
592
    DES_key_schedule key_sched_store;
 
593
    DES_key_schedule *key_sch = &key_sched_store;
 
594
#endif
 
595
    DES_cblock       key_struct;
 
596
#ifdef HAVE_AES
 
597
    AES_KEY aes_key;
 
598
    int new_ivlen = 0;
 
599
#endif
 
600
 
 
601
    DEBUGTRACE;
 
602
 
 
603
    /*
 
604
     * Sanity check.
 
605
     */
 
606
#if     !defined(SCAPI_AUTHPRIV)
 
607
    snmp_log(LOG_ERR, "Encryption support not enabled.\n");
 
608
    return SNMPERR_SC_NOT_CONFIGURED;
 
609
#endif
 
610
 
 
611
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
 
612
        || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)
 
613
        || (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
 
614
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
615
    } else if (ptlen > *ctlen) {
 
616
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
617
    }
 
618
#ifdef SNMP_TESTING_CODE
 
619
    {
 
620
        size_t          buf_len = 128, out_len = 0;
 
621
        u_char         *buf = (u_char *) malloc(buf_len);
 
622
 
 
623
        if (buf != NULL) {
 
624
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
 
625
                                         iv, ivlen)) {
 
626
                DEBUGMSGTL(("scapi", "encrypt: IV: %s/", buf));
 
627
            } else {
 
628
                DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]/", buf));
 
629
            }
 
630
            out_len = 0;
 
631
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
 
632
                                         key, keylen)) {
 
633
                DEBUGMSG(("scapi", "%s\n", buf));
 
634
            } else {
 
635
                DEBUGMSG(("scapi", "%s [TRUNCATED]\n", buf));
 
636
            }
 
637
            out_len = 0;
 
638
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
 
639
                                         plaintext, 16)) {
 
640
                DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf));
 
641
            } else {
 
642
                DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n",
 
643
                            buf));
 
644
            }
 
645
            free(buf);
 
646
        } else {
 
647
            DEBUGMSGTL(("scapi",
 
648
                        "encrypt: malloc fail for debug output\n"));
 
649
        }
 
650
    }
 
651
#endif                          /* SNMP_TESTING_CODE */
 
652
 
 
653
 
 
654
    /*
 
655
     * Determine privacy transform.
 
656
     */
 
657
    if (ISTRANSFORM(privtype, DESPriv)) {
 
658
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
 
659
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
 
660
        pad_size = properlength;
 
661
#ifdef HAVE_AES
 
662
    } else if (ISTRANSFORM(privtype, AES128Priv)) {
 
663
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128);
 
664
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128_IV);
 
665
    } else if (ISTRANSFORM(privtype, AES192Priv)) {
 
666
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192);
 
667
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV);
 
668
    } else if (ISTRANSFORM(privtype, AES256Priv)) {
 
669
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256);
 
670
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV);
 
671
#endif
 
672
    } else {
 
673
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
674
    }
 
675
 
 
676
    if ((keylen < properlength) || (ivlen < properlength_iv)) {
 
677
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
678
    }
 
679
 
 
680
    memset(my_iv, 0, sizeof(my_iv));
 
681
 
 
682
    if (ISTRANSFORM(privtype, DESPriv)) {
 
683
 
 
684
        /*
 
685
         * now calculate the padding needed 
 
686
         */
 
687
        pad = pad_size - (ptlen % pad_size);
 
688
        plast = (int) ptlen - (pad_size - pad);
 
689
        if (pad == pad_size)
 
690
            pad = 0;
 
691
        if (ptlen + pad > *ctlen) {
 
692
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);    /* not enough space */
 
693
        }
 
694
        if (pad > 0) {              /* copy data into pad block if needed */
 
695
            memcpy(pad_block, plaintext + plast, pad_size - pad);
 
696
            memset(&pad_block[pad_size - pad], pad, pad);   /* filling in padblock */
 
697
        }
 
698
 
 
699
        memcpy(key_struct, key, sizeof(key_struct));
 
700
        (void) DES_key_sched(&key_struct, key_sch);
 
701
 
 
702
        memcpy(my_iv, iv, ivlen);
 
703
        /*
 
704
         * encrypt the data 
 
705
         */
 
706
        DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch,
 
707
                         (DES_cblock *) my_iv, DES_ENCRYPT);
 
708
        if (pad > 0) {
 
709
            /*
 
710
             * then encrypt the pad block 
 
711
             */
 
712
            DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size,
 
713
                             key_sch, (DES_cblock *) my_iv, DES_ENCRYPT);
 
714
            *ctlen = plast + pad_size;
 
715
        } else {
 
716
            *ctlen = plast;
 
717
        }
 
718
    }
 
719
#ifdef HAVE_AES
 
720
    else if (ISTRANSFORM(privtype, AES128Priv) ||
 
721
             ISTRANSFORM(privtype, AES192Priv) ||
 
722
             ISTRANSFORM(privtype, AES256Priv)) {
 
723
        (void) AES_set_encrypt_key(key, properlength*8, &aes_key);
 
724
 
 
725
        memcpy(my_iv, iv, ivlen);
 
726
        /*
 
727
         * encrypt the data 
 
728
         */
 
729
        AES_cfb128_encrypt(plaintext, ciphertext, ptlen,
 
730
                           &aes_key, my_iv, &new_ivlen, AES_ENCRYPT);
 
731
        *ctlen = ptlen;
 
732
    }
 
733
#endif
 
734
  sc_encrypt_quit:
 
735
    /*
 
736
     * clear memory just in case 
 
737
     */
 
738
    memset(my_iv, 0, sizeof(my_iv));
 
739
    memset(pad_block, 0, sizeof(pad_block));
 
740
    memset(key_struct, 0, sizeof(key_struct));
 
741
#ifdef OLD_DES
 
742
    memset(&key_sch, 0, sizeof(key_sch));
 
743
#else
 
744
    memset(&key_sched_store, 0, sizeof(key_sched_store));
 
745
#endif
 
746
#ifdef HAVE_AES
 
747
    memset(&aes_key,0,sizeof(aes_key));
 
748
#endif
 
749
    return rval;
 
750
 
 
751
}                               /* end sc_encrypt() */
 
752
#elif defined(USE_PKCS)
 
753
{
 
754
    int             rval = SNMPERR_SUCCESS;
 
755
    u_int           properlength, properlength_iv;
 
756
    u_char          pkcs_des_key[8];
 
757
 
 
758
    DEBUGTRACE;
 
759
 
 
760
    /*
 
761
     * Sanity check.
 
762
     */
 
763
#if     !defined(SCAPI_AUTHPRIV)
 
764
    snmp_log(LOG_ERR, "Encryption support not enabled.\n");
 
765
    return SNMPERR_SC_NOT_CONFIGURED;
 
766
#endif
 
767
 
 
768
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
 
769
        || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)
 
770
        || (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
 
771
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
772
    } else if (ptlen > *ctlen) {
 
773
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
774
    }
 
775
 
 
776
    /*
 
777
     * Determine privacy transform.
 
778
     */
 
779
    if (ISTRANSFORM(privtype, DESPriv)) {
 
780
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
 
781
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
 
782
    } else {
 
783
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
784
    }
 
785
 
 
786
    if ((keylen < properlength) || (ivlen < properlength_iv)) {
 
787
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
 
788
    }
 
789
 
 
790
    if (ISTRANSFORM(privtype, DESPriv)) {
 
791
        memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
 
792
        memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
 
793
        rval = pkcs_encrpyt(CKM_DES_CBC, pkcs_des_key,
 
794
                sizeof(pkcs_des_key), iv, ivlen, plaintext, ptlen,
 
795
                ciphertext, ctlen);
 
796
    }
 
797
 
 
798
  sc_encrypt_quit:
 
799
    return rval;
 
800
}
 
801
#else
 
802
{
 
803
#       if USE_INTERNAL_MD5
 
804
    {
 
805
        snmp_log(LOG_ERR, "Encryption support not enabled.\n");
 
806
        DEBUGMSGTL(("scapi", "Encrypt function not defined.\n"));
 
807
        return SNMPERR_SC_GENERAL_FAILURE;
 
808
    }
 
809
 
 
810
#       else
 
811
    _SCAPI_NOT_CONFIGURED
 
812
#       endif                   /* USE_INTERNAL_MD5 */
 
813
}
 
814
#endif                          /* */
 
815
 
 
816
 
 
817
 
 
818
/*******************************************************************-o-******
 
819
 * sc_decrypt
 
820
 *
 
821
 * Parameters:
 
822
 *       privtype
 
823
 *      *key
 
824
 *       keylen
 
825
 *      *iv
 
826
 *       ivlen
 
827
 *      *ciphertext
 
828
 *       ctlen
 
829
 *      *plaintext
 
830
 *      *ptlen
 
831
 *      
 
832
 * Returns:
 
833
 *      SNMPERR_SUCCESS                 Success.
 
834
 *      SNMPERR_SC_NOT_CONFIGURED       Encryption is not supported.
 
835
 *      SNMPERR_SC_GENERAL_FAILURE      Any other error
 
836
 *
 
837
 *
 
838
 * Decrypt ciphertext into plaintext using key and iv.
 
839
 *
 
840
 * ptlen contains actual number of plaintext bytes in plaintext upon
 
841
 * successful return.
 
842
 */
 
843
int
 
844
sc_decrypt(const oid * privtype, size_t privtypelen,
 
845
           u_char * key, u_int keylen,
 
846
           u_char * iv, u_int ivlen,
 
847
           u_char * ciphertext, u_int ctlen,
 
848
           u_char * plaintext, size_t * ptlen)
 
849
#ifdef USE_OPENSSL
 
850
{
 
851
 
 
852
    int             rval = SNMPERR_SUCCESS;
 
853
    u_char          my_iv[128];
 
854
#ifdef OLD_DES
 
855
    DES_key_schedule key_sch;
 
856
#else
 
857
    DES_key_schedule key_sched_store;
 
858
    DES_key_schedule *key_sch = &key_sched_store;
 
859
#endif
 
860
    DES_cblock      key_struct;
 
861
    u_int           properlength, properlength_iv;
 
862
#ifdef HAVE_AES
 
863
    int new_ivlen = 0;
 
864
    AES_KEY aes_key;
 
865
#endif
 
866
 
 
867
    DEBUGTRACE;
 
868
 
 
869
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
 
870
        || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)
 
871
        || (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
 
872
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
 
873
    }
 
874
#ifdef SNMP_TESTING_CODE
 
875
    {
 
876
        size_t          buf_len = 128, out_len = 0;
 
877
        u_char         *buf = (u_char *) malloc(buf_len);
 
878
 
 
879
        if (buf != NULL) {
 
880
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
 
881
                                         iv, ivlen)) {
 
882
                DEBUGMSGTL(("scapi", "decrypt: IV: %s/", buf));
 
883
            } else {
 
884
                DEBUGMSGTL(("scapi", "decrypt: IV: %s [TRUNCATED]/", buf));
 
885
            }
 
886
            out_len = 0;
 
887
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
 
888
                                         key, keylen)) {
 
889
                DEBUGMSG(("scapi", "%s\n", buf));
 
890
            } else {
 
891
                DEBUGMSG(("scapi", "%s\n", buf));
 
892
            }
 
893
            free(buf);
 
894
        } else {
 
895
            DEBUGMSGTL(("scapi",
 
896
                        "decrypt: malloc fail for debug output\n"));
 
897
        }
 
898
    }
 
899
#endif                          /* SNMP_TESTING_CODE */
 
900
 
 
901
    /*
 
902
     * Determine privacy transform.
 
903
     */
 
904
    if (ISTRANSFORM(privtype, DESPriv)) {
 
905
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
 
906
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
 
907
#ifdef HAVE_AES
 
908
    } else if (ISTRANSFORM(privtype, AES128Priv)) {
 
909
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128);
 
910
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES128_IV);
 
911
    } else if (ISTRANSFORM(privtype, AES192Priv)) {
 
912
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192);
 
913
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV);
 
914
    } else if (ISTRANSFORM(privtype, AES256Priv)) {
 
915
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256);
 
916
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV);
 
917
#endif
 
918
    } else {
 
919
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
 
920
    }
 
921
 
 
922
    if ((keylen < properlength) || (ivlen < properlength_iv)) {
 
923
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
 
924
    }
 
925
 
 
926
    memset(my_iv, 0, sizeof(my_iv));
 
927
    if (ISTRANSFORM(privtype, DESPriv)) {
 
928
        memcpy(key_struct, key, sizeof(key_struct));
 
929
        (void) DES_key_sched(&key_struct, key_sch);
 
930
 
 
931
        memcpy(my_iv, iv, ivlen);
 
932
        DES_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch,
 
933
                        (DES_cblock *) my_iv, DES_DECRYPT);
 
934
        *ptlen = ctlen;
 
935
    }
 
936
#ifdef HAVE_AES
 
937
    else if (ISTRANSFORM(privtype, AES128Priv) ||
 
938
             ISTRANSFORM(privtype, AES192Priv) ||
 
939
             ISTRANSFORM(privtype, AES256Priv)) {
 
940
        (void) AES_set_encrypt_key(key, properlength*8, &aes_key);
 
941
 
 
942
        memcpy(my_iv, iv, ivlen);
 
943
        /*
 
944
         * encrypt the data 
 
945
         */
 
946
        AES_cfb128_encrypt(ciphertext, plaintext, ctlen,
 
947
                           &aes_key, my_iv, &new_ivlen, AES_DECRYPT);
 
948
        *ptlen = ctlen;
 
949
    }
 
950
#endif
 
951
 
 
952
    /*
 
953
     * exit cond 
 
954
     */
 
955
  sc_decrypt_quit:
 
956
#ifdef OLD_DES
 
957
    memset(&key_sch, 0, sizeof(key_sch));
 
958
#else
 
959
    memset(&key_sched_store, 0, sizeof(key_sched_store));
 
960
#endif
 
961
    memset(key_struct, 0, sizeof(key_struct));
 
962
    memset(my_iv, 0, sizeof(my_iv));
 
963
    return rval;
 
964
}                               /* USE OPEN_SSL */
 
965
#elif USE_PKCS                  /* USE PKCS */
 
966
{
 
967
    int             rval = SNMPERR_SUCCESS;
 
968
    u_int           properlength, properlength_iv;
 
969
    u_char          pkcs_des_key[8];
 
970
 
 
971
    DEBUGTRACE;
 
972
 
 
973
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
 
974
        || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)
 
975
        || (privtypelen != USM_LENGTH_OID_TRANSFORM)) {
 
976
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
 
977
    }
 
978
 
 
979
    /*
 
980
     * Determine privacy transform.
 
981
     */
 
982
    if (ISTRANSFORM(privtype, DESPriv)) {
 
983
        properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
 
984
        properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
 
985
    } else {
 
986
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
 
987
    }
 
988
 
 
989
    if ((keylen < properlength) || (ivlen < properlength_iv)) {
 
990
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
 
991
    }
 
992
 
 
993
    if (ISTRANSFORM(privtype, DESPriv)) {
 
994
        memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
 
995
        memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
 
996
        rval = pkcs_decrpyt(CKM_DES_CBC, pkcs_des_key, 
 
997
                sizeof(pkcs_des_key), iv, ivlen, ciphertext,
 
998
                ctlen, plaintext, ptlen);
 
999
        *ptlen = ctlen;
 
1000
    }
 
1001
 
 
1002
  sc_decrypt_quit:
 
1003
    return rval;
 
1004
}                               /* USE PKCS */
 
1005
#else
 
1006
{
 
1007
#if     !defined(SCAPI_AUTHPRIV)
 
1008
    snmp_log(LOG_ERR, "Encryption support not enabled.\n");
 
1009
    return SNMPERR_SC_NOT_CONFIGURED;
 
1010
#else
 
1011
#       if USE_INTERNAL_MD5
 
1012
    {
 
1013
        DEBUGMSGTL(("scapi", "Decryption function not defined.\n"));
 
1014
        return SNMPERR_SC_GENERAL_FAILURE;
 
1015
    }
 
1016
 
 
1017
#       else
 
1018
    _SCAPI_NOT_CONFIGURED
 
1019
#       endif                   /* USE_INTERNAL_MD5 */
 
1020
#endif                          /*  */
 
1021
}
 
1022
#endif                          /* USE_OPENSSL */