]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/snmp/lib/v2_0/src/scapi.c
unified MX27, MX25, MX37 trees
[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         if (maclen != USM_MD5_AND_SHA_AUTH_LEN) {
525             QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
526         }
527
528         /* 
529          * Generate a full hash of the message, then compare
530          * the result with the given MAC which may shorter than
531          * the full hash length.
532          */
533         rval = sc_generate_keyed_hash(  authtype, authtypelen,
534                                         key, keylen,
535                                         message, msglen,
536                                         buf, &buf_len);
537         QUITFUN(rval, sc_check_keyed_hash_quit);
538
539         if (maclen > msglen) {
540                 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
541
542         } else if ( memcmp(buf, MAC, maclen) != 0 ) {
543                 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
544         }
545
546
547 sc_check_keyed_hash_quit:
548         SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
549
550         return rval;
551
552 }  /* end sc_check_keyed_hash() */
553
554 #else
555 _SCAPI_NOT_CONFIGURED
556 #endif  /* USE_INTERNAL_MD5 */
557
558
559
560 /*******************************************************************-o-******
561  * sc_encrypt
562  *
563  * Parameters:
564  *       privtype       Type of privacy cryptographic transform.
565  *      *key            Key bits for crypting.
566  *       keylen         Length of key (buffer) in bytes.
567  *      *iv             IV bits for crypting.
568  *       ivlen          Length of iv (buffer) in bytes.
569  *      *plaintext      Plaintext to crypt.
570  *       ptlen          Length of plaintext.
571  *      *ciphertext     Ciphertext to crypt.
572  *      *ctlen          Length of ciphertext.
573  *      
574  * Returns:
575  *      SNMPERR_SUCCESS                 Success.
576  *      SNMPERR_SC_NOT_CONFIGURED       Encryption is not supported.
577  *      SNMPERR_SC_GENERAL_FAILURE      Any other error
578  *
579  *
580  * Encrypt plaintext into ciphertext using key and iv.
581  *
582  * ctlen contains actual number of crypted bytes in ciphertext upon
583  * successful return.
584  */
585 int
586 sc_encrypt(     oid    *privtype,       size_t privtypelen,
587                 u_char *key,            u_int  keylen,
588                 u_char *iv,             u_int  ivlen,
589                 u_char *plaintext,      u_int  ptlen,
590                 u_char *ciphertext,     size_t *ctlen)
591 #if defined(USE_OPENSSL) 
592 {
593         int             rval    = SNMPERR_SUCCESS;
594         u_int           transform,
595                         properlength,
596                         properlength_iv;
597         u_char          pad_block[32];  /* bigger than anything I need */
598         u_char          my_iv[32];      /* ditto */
599         int             pad, plast, pad_size;
600         des_key_schedule key_sch;
601         des_cblock      key_struct;
602
603         DEBUGTRACE;
604
605         /*
606          * Sanity check.
607          */
608 #if     !defined(SCAPI_AUTHPRIV)
609                 return SNMPERR_SC_NOT_CONFIGURED;
610 #endif
611
612         if ( !privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
613                 || (keylen<=0) || (ivlen<=0) || (ptlen<=0) || (*ctlen<=0)
614                 || (privtypelen != USM_LENGTH_OID_TRANSFORM) )
615         {
616                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
617         }
618         else if ( ptlen >= *ctlen) { 
619                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
620         }
621
622
623 #ifdef SNMP_TESTING_CODE
624 {
625         char buf[SNMP_MAXBUF];
626
627         sprint_hexstring(buf, iv, ivlen);
628         DEBUGMSGTL(("scapi", "encrypt: IV: %s/ ", buf));
629         sprint_hexstring(buf, key, keylen);
630         DEBUGMSG(("scapi","%s\n", buf));
631
632         sprint_hexstring(buf, plaintext, 16);
633         DEBUGMSGTL(("scapi","encrypt: string: %s\n", buf));
634 }
635 #endif /* SNMP_TESTING_CODE */
636
637
638         /*
639          * Determine privacy transform.
640          */
641         if ( ISTRANSFORM(privtype, DESPriv) ) {
642                 properlength    = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
643                 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
644                 pad_size = properlength;
645         } else {
646                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
647         }
648
649         if ( (keylen<properlength) || (ivlen<properlength_iv) ) {
650                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
651         }
652
653         else if ( (keylen<properlength) || (ivlen<properlength_iv) ) {
654                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
655         }
656
657 /* now calculate the padding needed */
658         pad = pad_size - (ptlen % pad_size);
659         if (ptlen + pad > *ctlen) { 
660                 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); /* not enough space */
661         }
662         memset(pad_block, 0, sizeof(pad_block));
663         plast = (int) ptlen - (pad_size - pad);
664         if (pad > 0)  /* copy data into pad block if needed */
665                 memcpy( pad_block, plaintext + plast, pad_size - pad);
666         memset(&pad_block[pad_size-pad], pad, pad); /* filling in padblock */
667
668         memset(my_iv, 0, sizeof(my_iv));
669
670         if ( ISTRANSFORM(privtype, DESPriv) ) {
671                 memcpy(key_struct, key, sizeof(key_struct));
672                 (void) des_key_sched(&key_struct, key_sch);
673
674                 memcpy(my_iv, iv, ivlen);
675                 /* encrypt the data */
676                 des_ncbc_encrypt(plaintext, ciphertext, plast, key_sch, 
677                                  (des_cblock *) &my_iv, DES_ENCRYPT);
678                 /* then encrypt the pad block */
679                 des_ncbc_encrypt(pad_block, ciphertext+plast, pad_size, 
680                                  key_sch, (des_cblock *)&my_iv, DES_ENCRYPT);
681                 *ctlen = plast + pad_size;
682         }
683 sc_encrypt_quit:
684         /* clear memory just in case */
685         memset(my_iv, 0, sizeof(my_iv));
686         memset(pad_block, 0, sizeof(pad_block));
687         memset(key_struct, 0, sizeof(key_struct));
688         memset(key_sch, 0, sizeof(key_sch));
689         return rval;
690
691 }  /* end sc_encrypt() */
692
693 #else
694 {
695 #       if USE_INTERNAL_MD5
696         {
697                 DEBUGMSGTL(("scapi","Encrypt function not defined.\n"));
698                 return SNMPERR_SC_GENERAL_FAILURE;
699         }
700
701 #       else
702                 _SCAPI_NOT_CONFIGURED
703
704 #       endif /* USE_INTERNAL_MD5 */
705                         }
706 #endif                                                  /* */
707
708
709
710 /*******************************************************************-o-******
711  * sc_decrypt
712  *
713  * Parameters:
714  *       privtype
715  *      *key
716  *       keylen
717  *      *iv
718  *       ivlen
719  *      *ciphertext
720  *       ctlen
721  *      *plaintext
722  *      *ptlen
723  *      
724  * Returns:
725  *      SNMPERR_SUCCESS                 Success.
726  *      SNMPERR_SC_NOT_CONFIGURED       Encryption is not supported.
727  *      SNMPERR_SC_GENERAL_FAILURE      Any other error
728  *
729  *
730  * Decrypt ciphertext into plaintext using key and iv.
731  *
732  * ptlen contains actual number of plaintext bytes in plaintext upon
733  * successful return.
734  */
735 int
736 sc_decrypt(     oid    *privtype,       size_t privtypelen,
737                 u_char *key,            u_int  keylen,
738                 u_char *iv,             u_int  ivlen,
739                 u_char *ciphertext,     u_int  ctlen,
740                 u_char *plaintext,      size_t *ptlen)
741 #ifdef USE_OPENSSL
742 {
743
744         int rval = SNMPERR_SUCCESS;
745         int i, j; 
746         u_char *my_iv[32];
747         des_key_schedule key_sch;
748         des_cblock  key_struct;
749         u_int           properlength,
750                         properlength_iv;
751
752         DEBUGTRACE;
753
754         if ( !privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
755                 || (ctlen<=0) || (*ptlen<=0) || (*ptlen < ctlen)
756                 || (privtypelen != USM_LENGTH_OID_TRANSFORM) )
757         {
758                 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
759         }
760
761
762 #ifdef SNMP_TESTING_CODE
763 {
764         char buf[SNMP_MAXBUF];
765
766         sprint_hexstring(buf, iv, ivlen);
767         DEBUGMSGTL(("scapi", "decrypt: IV: %s/ ", buf));
768         sprint_hexstring(buf, key, keylen);
769         DEBUGMSG(("scapi","%s\n", buf));
770 }
771 #endif /* SNMP_TESTING_CODE */
772
773         /*
774          * Determine privacy transform.
775          */
776         if ( ISTRANSFORM(privtype, DESPriv) ) {
777                 properlength    = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES);
778                 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV);
779
780         } else {
781                 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
782         }
783
784         if ( (keylen<properlength) || (ivlen<properlength_iv) ) {
785                 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
786         }
787         
788         memset(my_iv, 0, sizeof(my_iv));
789         if (ISTRANSFORM(privtype, DESPriv)) {
790                 memcpy(key_struct, key, sizeof(key_struct));
791                 (void) des_key_sched(&key_struct, key_sch);
792         
793                 memcpy(my_iv, iv, ivlen);
794                 des_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch, 
795                                 (des_cblock *) &my_iv, DES_DECRYPT);
796         }
797
798 /* exit cond */
799 sc_decrypt_quit:
800         memset(key_sch, 0, sizeof(key_sch));
801         memset(key_struct, 0, sizeof(key_struct));
802         memset(my_iv, 0, sizeof(my_iv));
803         return rval;
804 }  
805 #else   /* USE OPEN_SSL */
806 {
807 #if     !defined(SCAPI_AUTHPRIV)
808                 return SNMPERR_SC_NOT_CONFIGURED;
809 #else
810 #       if USE_INTERNAL_MD5
811         {
812                 DEBUGMSGTL(("scapi","Decryption function not defined.\n"));
813                 return SNMPERR_SC_GENERAL_FAILURE;
814         }
815
816 #       else
817                 _SCAPI_NOT_CONFIGURED
818
819 #       endif /* USE_INTERNAL_MD5 */
820 #endif                                                  /*  */
821                         }
822 #endif /* USE_OPENSSL */
823
824 #endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */