]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/snmp/lib/v2_0/src/scapi.c
Initial revision
[karo-tx-redboot.git] / packages / net / snmp / lib / v2_0 / src / scapi.c
1 //==========================================================================
2 //
3 //      ./lib/current/src/scapi.c
4 //
5 //
6 //==========================================================================
7 //####ECOSGPLCOPYRIGHTBEGIN####
8 // -------------------------------------------
9 // This file is part of eCos, the Embedded Configurable Operating System.
10 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
11 //
12 // eCos is free software; you can redistribute it and/or modify it under
13 // the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 2 or (at your option) any later version.
15 //
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19 // for more details.
20 //
21 // You should have received a copy of the GNU General Public License along
22 // with eCos; if not, write to the Free Software Foundation, Inc.,
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 //
25 // As a special exception, if other files instantiate templates or use macros
26 // or inline functions from this file, or you compile this file and link it
27 // with other works to produce a work based on this file, this file does not
28 // by itself cause the resulting work to be covered by the GNU General Public
29 // License. However the source code for this file must still be made available
30 // in accordance with section (3) of the GNU General Public License.
31 //
32 // This exception does not invalidate any other reasons why a work based on
33 // this file might be covered by the GNU General Public License.
34 //
35 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
36 // at http://sources.redhat.com/ecos/ecos-license/
37 // -------------------------------------------
38 //####ECOSGPLCOPYRIGHTEND####
39 //####UCDSNMPCOPYRIGHTBEGIN####
40 //
41 // -------------------------------------------
42 //
43 // Portions of this software may have been derived from the UCD-SNMP
44 // project,  <http://ucd-snmp.ucdavis.edu/>  from the University of
45 // California at Davis, which was originally based on the Carnegie Mellon
46 // University SNMP implementation.  Portions of this software are therefore
47 // covered by the appropriate copyright disclaimers included herein.
48 //
49 // The release used was version 4.1.2 of May 2000.  "ucd-snmp-4.1.2"
50 // -------------------------------------------
51 //
52 //####UCDSNMPCOPYRIGHTEND####
53 //==========================================================================
54 //#####DESCRIPTIONBEGIN####
55 //
56 // Author(s):    hmt
57 // Contributors: hmt
58 // Date:         2000-05-30
59 // Purpose:      Port of UCD-SNMP distribution to eCos.
60 // Description:  
61 //              
62 //
63 //####DESCRIPTIONEND####
64 //
65 //==========================================================================
66 /********************************************************************
67        Copyright 1989, 1991, 1992 by Carnegie Mellon University
68
69                           Derivative Work -
70 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
71
72                          All Rights Reserved
73
74 Permission to use, copy, modify and distribute this software and its
75 documentation for any purpose and without fee is hereby granted,
76 provided that the above copyright notice appears in all copies and
77 that both that copyright notice and this permission notice appear in
78 supporting documentation, and that the name of CMU and The Regents of
79 the University of California not be used in advertising or publicity
80 pertaining to distribution of the software without specific written
81 permission.
82
83 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
84 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
85 WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL CMU OR
86 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
87 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
88 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
89 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
90 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
91 *********************************************************************/
92 /*
93  * scapi.c
94  *
95  */
96
97 #include <config.h>
98
99 #ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
100 #include <sys/types.h>
101 #if HAVE_WINSOCK_H
102 #include <winsock.h>
103 #endif
104 #ifdef HAVE_STDLIB_H
105 #include <stdlib.h>
106 #endif
107 #if HAVE_STRING_H
108 #include <string.h>
109 #else
110 #include <strings.h>
111 #endif
112 #if TIME_WITH_SYS_TIME
113 # ifdef WIN32
114 #  include <sys/timeb.h>
115 # else
116 #  include <sys/time.h>
117 # endif
118 # include <time.h>
119 #else
120 # if HAVE_SYS_TIME_H
121 #  include <sys/time.h>
122 # else
123 #  include <time.h>
124 # endif
125 #endif
126 #ifdef HAVE_NETINET_IN_H
127 #include <netinet/in.h>
128 #endif
129
130 #ifdef USE_INTERNAL_MD5
131 #include "md5.h"
132 #endif
133 #include "asn1.h"
134 #include "tools.h"
135 #include "snmp_api.h"
136 #include "callback.h"
137 #include "snmpusm.h"
138 #include "keytools.h"
139 #include "snmp_debug.h"
140 #include "scapi.h"
141 #include "snmp_impl.h"
142 #include "system.h"
143
144 #include "transform_oids.h"
145
146 #ifdef USE_OPENSSL
147 #include <openssl/hmac.h>
148 #include <openssl/evp.h>
149 #include <openssl/rand.h>
150 #endif
151
152 #ifdef QUITFUN
153 #undef QUITFUN
154 #define QUITFUN(e, l)                                   \
155         if (e != SNMPERR_SUCCESS) {                     \
156                 rval = SNMPERR_SC_GENERAL_FAILURE;      \
157                 goto l ;                                \
158         }
159 #endif
160
161
162 /*
163   sc_get_properlength(oid *hashtype, u_int hashtype_len):
164
165   Given a hashing type ("hashtype" and its length hashtype_len), return
166   the length of the hash result.
167
168   Returns either the length or SNMPERR_GENERR for an unknown hashing type.
169 */
170 int
171 sc_get_properlength(oid *hashtype, u_int hashtype_len)
172 {
173   DEBUGTRACE;
174   /*
175    * Determine transform type hash length.
176    */
177   if ( ISTRANSFORM(hashtype, HMACMD5Auth)) {
178     return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5);
179   }
180   else if ( ISTRANSFORM(hashtype, HMACSHA1Auth) ) {
181     return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1);
182   }
183   return SNMPERR_GENERR;
184 }
185
186
187 /*******************************************************************-o-******
188  * sc_init
189  *
190  * Returns:
191  *      SNMPERR_SUCCESS                 Success.
192  */
193 int
194 sc_init(void)
195 {
196   int           rval = SNMPERR_SUCCESS;
197
198 #ifndef USE_OPENSSL
199 #ifdef USE_INTERNAL_MD5
200   struct timeval tv;
201   
202   DEBUGTRACE;
203
204   gettimeofday(&tv,(struct timezone *)0);
205   
206   srandom(tv.tv_sec ^ tv.tv_usec);
207 #else
208   rval = SNMPERR_SC_NOT_CONFIGURED;
209 #endif
210   /* XXX ogud: The only reason to do anything here with openssl is to 
211    * XXX ogud: seed random number generator 
212    */
213 #endif  /* ifndef USE_OPENSSL */
214         return rval;
215 }  /* end sc_init() */
216
217 /*******************************************************************-o-******
218  * sc_random
219  *
220  * Parameters:
221  *      *buf            Pre-allocated buffer.
222  *      *buflen         Size of buffer.
223  *      
224  * Returns:
225  *      SNMPERR_SUCCESS                 Success.
226  */
227 int
228 sc_random(u_char *buf, size_t *buflen)
229 #if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL)
230 {
231   int           rval = SNMPERR_SUCCESS;
232 #ifdef USE_INTERNAL_MD5
233   int i;
234   int rndval;
235   u_char *ucp = buf;
236 #endif
237
238   DEBUGTRACE;
239
240 #ifdef USE_OPENSSL
241   RAND_bytes(buf, *buflen); /* will never fail */
242 #else   /* USE_INTERNAL_MD5 */
243   /* fill the buffer with random integers.  Note that random()
244      is defined in config.h and may not be truly the random()
245      system call if something better existed */
246   rval = *buflen - *buflen%sizeof(rndval);
247   for(i = 0; i < rval; i += sizeof(rndval)) {
248     rndval = random();
249     memcpy(ucp, &rndval, sizeof(rndval));
250     ucp += sizeof(rndval);
251   }
252   
253   rndval = random();
254   memcpy(ucp, &rndval, *buflen%sizeof(rndval));
255   
256   rval = SNMPERR_SUCCESS;
257 #endif  /* USE_OPENSSL */
258   return rval;
259
260 }  /* end sc_random() */
261
262 #else
263 _SCAPI_NOT_CONFIGURED
264 #endif                                                  /*  */
265
266
267
268 /*******************************************************************-o-******
269  * sc_generate_keyed_hash
270  *
271  * Parameters:
272  *       authtype       Type of authentication transform.
273  *       authtypelen
274  *      *key            Pointer to key (Kul) to use in keyed hash.
275  *       keylen         Length of key in bytes.
276  *      *message        Pointer to the message to hash.
277  *       msglen         Length of the message.
278  *      *MAC            Will be returned with allocated bytes containg hash.
279  *      *maclen         Length of the hash buffer in bytes; also indicates
280  *                              whether the MAC should be truncated.
281  *      
282  * Returns:
283  *      SNMPERR_SUCCESS                 Success.
284  *      SNMPERR_GENERR                  All errs
285  *
286  *
287  * A hash of the first msglen bytes of message using a keyed hash defined
288  * by authtype is created and stored in MAC.  MAC is ASSUMED to be a buffer
289  * of at least maclen bytes.  If the length of the hash is greater than
290  * maclen, it is truncated to fit the buffer.  If the length of the hash is
291  * less than maclen, maclen set to the number of hash bytes generated.
292  *
293  * ASSUMED that the number of hash bits is a multiple of 8.
294  */
295 int
296 sc_generate_keyed_hash( oid     *authtype,      size_t authtypelen,
297                         u_char  *key,           u_int  keylen,
298                         u_char  *message,       u_int  msglen,
299                         u_char  *MAC,           size_t *maclen)
300 #if  defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL)
301 {
302   int            rval    = SNMPERR_SUCCESS;
303   int            properlength;
304
305   u_char         buf[SNMP_MAXBUF_SMALL];
306 #if  defined(USE_OPENSSL)
307   int            buf_len = sizeof(buf);
308   u_char        *bufp = buf;
309 #endif
310   
311   DEBUGTRACE;
312
313 #ifdef SNMP_TESTING_CODE
314 {
315   int i;
316   DEBUGMSG(("sc_generate_keyed_hash", "sc_generate_keyed_hash(): key=0x"));
317   for(i=0; i< keylen; i++)
318     DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff));
319   DEBUGMSG(("sc_generate_keyed_hash"," (%d)\n", keylen));
320 }
321 #endif /* SNMP_TESTING_CODE */
322
323 /*
324  * Sanity check.
325  */
326  if ( !authtype || !key || !message || !MAC || !maclen
327       || (keylen<=0) || (msglen<=0) || (*maclen<=0)
328       || (authtypelen != USM_LENGTH_OID_TRANSFORM) )
329    {
330      QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
331    }
332  
333  properlength = sc_get_properlength(authtype, authtypelen);
334  if (properlength == SNMPERR_GENERR)
335    return properlength;
336  
337  if ( ((int)keylen < properlength) ) {
338    QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
339  }
340  
341
342 #ifdef USE_OPENSSL
343  /*
344   * Determine transform type.
345   */
346    if (ISTRANSFORM(authtype, HMACMD5Auth))
347      HMAC(EVP_md5(), key, keylen, message, msglen,  
348           buf, &buf_len);
349    else if (ISTRANSFORM(authtype, HMACSHA1Auth)) 
350      HMAC(EVP_sha1(), key, keylen, message, msglen,  
351           buf, &buf_len);
352    else {
353      QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
354    }
355    if (buf_len != properlength) {
356      QUITFUN(rval, sc_generate_keyed_hash_quit);
357    }
358    if (*maclen > buf_len) 
359      *maclen = buf_len;
360    memcpy(MAC, buf, *maclen);
361 #else 
362  if ((int)*maclen > properlength)
363    *maclen = properlength;
364  if (MDsign(message, msglen, MAC, *maclen, key, keylen)) {
365    rval = SNMPERR_GENERR;
366    goto sc_generate_keyed_hash_quit;
367  }
368 #endif /* USE_OPENSSL */
369
370 #ifdef SNMP_TESTING_CODE
371  {
372    char    *s;
373    int      len = binary_to_hex(MAC, *maclen, &s);
374    
375    DEBUGMSGTL(("scapi","Full v3 message hash: %s\n", s));
376    SNMP_ZERO(s, len);
377    SNMP_FREE(s);
378  }
379 #endif
380  
381  sc_generate_keyed_hash_quit:
382  SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
383  return rval;
384 }  /* end sc_generate_keyed_hash() */
385
386 #else
387 _SCAPI_NOT_CONFIGURED
388 #endif                                                  /* */
389
390
391 /* sc_hash(): a generic wrapper around whatever hashing package we are using.
392
393    IN:
394      hashtype    - oid pointer to a hash type
395      hashtypelen - length of oid pointer
396      buf         - u_char buffer to be hashed
397      buf_len     - integer length of buf data
398      MAC_len     - length of the passed MAC buffer size.
399     
400    OUT:    
401      MAC         - pre-malloced space to store hash output.
402      MAC_len     - length of MAC output to the MAC buffer.
403
404    Returns:
405      SNMPERR_SUCCESS            Success.
406      SNMP_SC_GENERAL_FAILURE    Any error.
407 */
408
409 int
410 sc_hash(oid *hashtype, size_t hashtypelen, u_char *buf, size_t buf_len,
411         u_char *MAC, size_t *MAC_len)
412 #if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL)
413 {
414   int   rval       = SNMPERR_SUCCESS;
415
416 #ifdef USE_OPENSSL 
417   EVP_MD *hash(void);
418   HMAC_CTX *c = NULL; 
419 #endif
420
421   DEBUGTRACE;
422
423   if (hashtype == NULL || hashtypelen < 0 || buf == NULL ||
424       buf_len < 0 || MAC == NULL ||  MAC_len == NULL ||
425       (int)(*MAC_len) < sc_get_properlength(hashtype, hashtypelen))
426     return (SNMPERR_GENERR);
427
428 #ifdef USE_OPENSSL 
429   /*
430    * Determine transform type.
431    */
432   c = malloc(sizeof(HMAC_CTX));
433   if (c == NULL)
434     return (SNMPERR_GENERR);
435
436   if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
437     EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_md5());
438   }
439   else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
440     EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_sha1());
441   }
442   else {
443     return(SNMPERR_GENERR);
444   }
445   EVP_DigestUpdate(&c->md_ctx, buf, buf_len);
446   EVP_DigestFinal(&(c->md_ctx), MAC, MAC_len);
447   free(c);
448   return (rval);
449 #else /* USE_INTERNAL_MD5 */
450
451   if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
452     return SNMPERR_GENERR;
453   }
454   if (*MAC_len > 16)
455     *MAC_len = 16;
456   return (rval);
457
458 #endif /* USE_OPENSSL */
459 }
460 #else /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */
461 _SCAPI_NOT_CONFIGURED
462 #endif /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */
463
464
465
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(    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)
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         {
520                 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
521         }
522
523
524         /* 
525          * Generate a full hash of the message, then compare
526          * the result with the given MAC which may shorter than
527          * the full hash length.
528          */
529         rval = sc_generate_keyed_hash(  authtype, authtypelen,
530                                         key, keylen,
531                                         message, msglen,
532                                         buf, &buf_len);
533         QUITFUN(rval, sc_check_keyed_hash_quit);
534
535         if (maclen > msglen) {
536                 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
537
538         } else if ( memcmp(buf, MAC, maclen) != 0 ) {
539                 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
540         }
541
542
543 sc_check_keyed_hash_quit:
544         SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
545
546         return rval;
547
548 }  /* end sc_check_keyed_hash() */
549
550 #else
551 _SCAPI_NOT_CONFIGURED
552 #endif  /* USE_INTERNAL_MD5 */
553
554
555
556 /*******************************************************************-o-******
557  * sc_encrypt
558  *
559  * Parameters:
560  *       privtype       Type of privacy cryptographic transform.
561  *      *key            Key bits for crypting.
562  *       keylen         Length of key (buffer) in bytes.
563  *      *iv             IV bits for crypting.
564  *       ivlen          Length of iv (buffer) in bytes.
565  *      *plaintext      Plaintext to crypt.
566  *       ptlen          Length of plaintext.
567  *      *ciphertext     Ciphertext to crypt.
568  *      *ctlen          Length of ciphertext.
569  *      
570  * Returns:
571  *      SNMPERR_SUCCESS                 Success.
572  *      SNMPERR_SC_NOT_CONFIGURED       Encryption is not supported.
573  *      SNMPERR_SC_GENERAL_FAILURE      Any other error
574  *
575  *
576  * Encrypt plaintext into ciphertext using key and iv.
577  *
578  * ctlen contains actual number of crypted bytes in ciphertext upon
579  * successful return.
580  */
581 int
582 sc_encrypt(     oid    *privtype,       size_t privtypelen,
583                 u_char *key,            u_int  keylen,
584                 u_char *iv,             u_int  ivlen,
585                 u_char *plaintext,      u_int  ptlen,
586                 u_char *ciphertext,     size_t *ctlen)
587 #if defined(USE_OPENSSL) 
588 {
589         int             rval    = SNMPERR_SUCCESS;
590         u_int           transform,
591                         properlength,
592                         properlength_iv;
593         u_char          pad_block[32];  /* bigger than anything I need */
594         u_char          my_iv[32];      /* ditto */
595         int             pad, plast, pad_size;
596         des_key_schedule key_sch;
597         des_cblock      key_struct;
598
599         DEBUGTRACE;
600
601         /*
602          * Sanity check.
603          */
604 #if     !defined(SCAPI_AUTHPRIV)
605                 return SNMPERR_SC_NOT_CONFIGURED;
606 #endif
607
608         if ( !privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
609                 || (keylen<=0) || (ivlen<=0) || (ptlen<=0) || (*ctlen<=0)
610                 || (privtypelen != USM_LENGTH_OID_TRANSFORM) )
611         {
612                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
613         }
614         else if ( ptlen >= *ctlen) { 
615                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
616         }
617
618
619 #ifdef SNMP_TESTING_CODE
620 {
621         char buf[SNMP_MAXBUF];
622
623         sprint_hexstring(buf, iv, ivlen);
624         DEBUGMSGTL(("scapi", "encrypt: IV: %s/ ", buf));
625         sprint_hexstring(buf, key, keylen);
626         DEBUGMSG(("scapi","%s\n", buf));
627
628         sprint_hexstring(buf, plaintext, 16);
629         DEBUGMSGTL(("scapi","encrypt: string: %s\n", buf));
630 }
631 #endif /* SNMP_TESTING_CODE */
632
633
634         /*
635          * Determine privacy transform.
636          */
637         if ( ISTRANSFORM(privtype, DESPriv) ) {
638                 properlength    = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
639                 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
640                 pad_size = properlength;
641         } else {
642                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
643         }
644
645         if ( (keylen<properlength) || (ivlen<properlength_iv) ) {
646                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
647         }
648
649         else if ( (keylen<properlength) || (ivlen<properlength_iv) ) {
650                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
651         }
652
653 /* now calculate the padding needed */
654         pad = pad_size - (ptlen % pad_size);
655         if (ptlen + pad > *ctlen) { 
656                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); /* not enough space */
657         }
658         memset(pad_block, 0, sizeof(pad_block));
659         plast = (int) ptlen - (pad_size - pad);
660         if (pad > 0)  /* copy data into pad block if needed */
661                 memcpy( pad_block, plaintext + plast, pad_size - pad);
662         memset(&pad_block[pad_size-pad], pad, pad); /* filling in padblock */
663
664         memset(my_iv, 0, sizeof(my_iv));
665
666         if ( ISTRANSFORM(privtype, DESPriv) ) {
667                 memcpy(key_struct, key, sizeof(key_struct));
668                 (void) des_key_sched(&key_struct, key_sch);
669
670                 memcpy(my_iv, iv, ivlen);
671                 /* encrypt the data */
672                 des_ncbc_encrypt(plaintext, ciphertext, plast, key_sch, 
673                                  (des_cblock *) &my_iv, DES_ENCRYPT);
674                 /* then encrypt the pad block */
675                 des_ncbc_encrypt(pad_block, ciphertext+plast, pad_size, 
676                                  key_sch, (des_cblock *)&my_iv, DES_ENCRYPT);
677                 *ctlen = plast + pad_size;
678         }
679 sc_encrypt_quit:
680         /* clear memory just in case */
681         memset(my_iv, 0, sizeof(my_iv));
682         memset(pad_block, 0, sizeof(pad_block));
683         memset(key_struct, 0, sizeof(key_struct));
684         memset(key_sch, 0, sizeof(key_sch));
685         return rval;
686
687 }  /* end sc_encrypt() */
688
689 #else
690 {
691 #       if USE_INTERNAL_MD5
692         {
693                 DEBUGMSGTL(("scapi","Encrypt function not defined.\n"));
694                 return SNMPERR_SC_GENERAL_FAILURE;
695         }
696
697 #       else
698                 _SCAPI_NOT_CONFIGURED
699
700 #       endif /* USE_INTERNAL_MD5 */
701                         }
702 #endif                                                  /* */
703
704
705
706 /*******************************************************************-o-******
707  * sc_decrypt
708  *
709  * Parameters:
710  *       privtype
711  *      *key
712  *       keylen
713  *      *iv
714  *       ivlen
715  *      *ciphertext
716  *       ctlen
717  *      *plaintext
718  *      *ptlen
719  *      
720  * Returns:
721  *      SNMPERR_SUCCESS                 Success.
722  *      SNMPERR_SC_NOT_CONFIGURED       Encryption is not supported.
723  *      SNMPERR_SC_GENERAL_FAILURE      Any other error
724  *
725  *
726  * Decrypt ciphertext into plaintext using key and iv.
727  *
728  * ptlen contains actual number of plaintext bytes in plaintext upon
729  * successful return.
730  */
731 int
732 sc_decrypt(     oid    *privtype,       size_t privtypelen,
733                 u_char *key,            u_int  keylen,
734                 u_char *iv,             u_int  ivlen,
735                 u_char *ciphertext,     u_int  ctlen,
736                 u_char *plaintext,      size_t *ptlen)
737 #ifdef USE_OPENSSL
738 {
739
740         int rval = SNMPERR_SUCCESS;
741         int i, j; 
742         u_char *my_iv[32];
743         des_key_schedule key_sch;
744         des_cblock  key_struct;
745         u_int           properlength,
746                         properlength_iv;
747
748         DEBUGTRACE;
749
750         if ( !privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
751                 || (ctlen<=0) || (*ptlen<=0) || (*ptlen < ctlen)
752                 || (privtypelen != USM_LENGTH_OID_TRANSFORM) )
753         {
754                 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
755         }
756
757
758 #ifdef SNMP_TESTING_CODE
759 {
760         char buf[SNMP_MAXBUF];
761
762         sprint_hexstring(buf, iv, ivlen);
763         DEBUGMSGTL(("scapi", "decrypt: IV: %s/ ", buf));
764         sprint_hexstring(buf, key, keylen);
765         DEBUGMSG(("scapi","%s\n", buf));
766 }
767 #endif /* SNMP_TESTING_CODE */
768
769         /*
770          * Determine privacy transform.
771          */
772         if ( ISTRANSFORM(privtype, DESPriv) ) {
773                 properlength    = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
774                 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
775
776         } else {
777                 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
778         }
779
780         if ( (keylen<properlength) || (ivlen<properlength_iv) ) {
781                 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
782         }
783         
784         memset(my_iv, 0, sizeof(my_iv));
785         if (ISTRANSFORM(privtype, DESPriv)) {
786                 memcpy(key_struct, key, sizeof(key_struct));
787                 (void) des_key_sched(&key_struct, key_sch);
788         
789                 memcpy(my_iv, iv, ivlen);
790                 des_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch, 
791                                 (des_cblock *) &my_iv, DES_DECRYPT);
792         }
793
794 /* exit cond */
795 sc_decrypt_quit:
796         memset(key_sch, 0, sizeof(key_sch));
797         memset(key_struct, 0, sizeof(key_struct));
798         memset(my_iv, 0, sizeof(my_iv));
799         return rval;
800 }  
801 #else   /* USE OPEN_SSL */
802 {
803 #if     !defined(SCAPI_AUTHPRIV)
804                 return SNMPERR_SC_NOT_CONFIGURED;
805 #else
806 #       if USE_INTERNAL_MD5
807         {
808                 DEBUGMSGTL(("scapi","Decryption function not defined.\n"));
809                 return SNMPERR_SC_GENERAL_FAILURE;
810         }
811
812 #       else
813                 _SCAPI_NOT_CONFIGURED
814
815 #       endif /* USE_INTERNAL_MD5 */
816 #endif                                                  /*  */
817                         }
818 #endif /* USE_OPENSSL */
819
820 #endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */