Annotation of embedaddon/libpdel/util/rsa_util.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (c) 2001-2002 Packet Design, LLC.
                      4:  * All rights reserved.
                      5:  * 
                      6:  * Subject to the following obligations and disclaimer of warranty,
                      7:  * use and redistribution of this software, in source or object code
                      8:  * forms, with or without modifications are expressly permitted by
                      9:  * Packet Design; provided, however, that:
                     10:  * 
                     11:  *    (i)  Any and all reproductions of the source or object code
                     12:  *         must include the copyright notice above and the following
                     13:  *         disclaimer of warranties; and
                     14:  *    (ii) No rights are granted, in any manner or form, to use
                     15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
                     16:  *         on advertising, endorsements, or otherwise except as such
                     17:  *         appears in the above copyright notice or in the software.
                     18:  * 
                     19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
                     20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
                     21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
                     22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
                     23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
                     24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
                     25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
                     26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
                     27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
                     28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
                     29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
                     30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
                     31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
                     32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
                     33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
                     35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
                     36:  * THE POSSIBILITY OF SUCH DAMAGE.
                     37:  *
                     38:  * Author: Archie Cobbs <archie@freebsd.org>
                     39:  */
                     40: 
                     41: #include <sys/param.h>
                     42: #include <sys/syslog.h>
                     43: 
                     44: #include <stdio.h>
                     45: #include <stdlib.h>
                     46: #include <stdarg.h>
                     47: #include <string.h>
                     48: #include <unistd.h>
                     49: #include <errno.h>
                     50: 
                     51: #include <openssl/ssl.h>
                     52: #include <openssl/err.h>
                     53: #include <openssl/md5.h>
                     54: 
                     55: #include "structs/structs.h"
                     56: #include "structs/type/array.h"
                     57: 
                     58: #include "util/rsa_util.h"
                     59: #include "util/typed_mem.h"
                     60: 
                     61: static int     rsa_util_verify_rsa(RSA *rsa, const u_char *md5,
                     62:                        const u_char *sig, size_t siglen);
                     63: 
                     64: /*
                     65:  * Create an RSA signature given an RSA private key filename.
                     66:  *
                     67:  * We assume the thing to be signed is an MD5 hash.
                     68:  *
                     69:  * Returns the signature length, or -1 if error.
                     70:  */
                     71: int
                     72: rsa_util_sign(const char *privkeyfile,
                     73:        const u_char *md5, u_char *sig, size_t siglen)
                     74: {
                     75:        u_char *vbuf = NULL;                    /* encrypted signature (md5) */
                     76:        FILE *fp = NULL;
                     77:        RSA *rsa = NULL;
                     78:        int rtn = -1;
                     79:        int vlen;
                     80: 
                     81:        /* Open file */
                     82:        if ((fp = fopen(privkeyfile, "r")) == NULL) {
                     83:                fprintf(stderr, "%s: %s\n", privkeyfile, strerror(errno));
                     84:                goto done;
                     85:        }
                     86: 
                     87:        /* Read private key */
                     88:        if ((rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) {
                     89:                ERR_print_errors_fp(stderr);
                     90:                goto done;
                     91:        }
                     92: 
                     93:        /* Check buffer length */
                     94:        if (siglen < RSA_size(rsa)) {
                     95:                errno = EINVAL;
                     96:                goto done;
                     97:        }
                     98: 
                     99:        /* Encrypt using private key */
                    100:        if ((vlen = RSA_private_encrypt(MD5_DIGEST_LENGTH,
                    101:            (u_char *)md5, sig, rsa, RSA_PKCS1_PADDING)) <= 0) {
                    102:                ERR_print_errors_fp(stderr);
                    103:                goto done;
                    104:        }
                    105: 
                    106:        /* OK */
                    107:        rtn = vlen;
                    108: 
                    109: done:
                    110:        /* Clean up */
                    111:        FREE(TYPED_MEM_TEMP, vbuf);
                    112:        RSA_free(rsa);
                    113:        if (fp != NULL)
                    114:                fclose(fp);
                    115: 
                    116:        /* Return result */
                    117:        return (rtn);
                    118: }
                    119: 
                    120: /*
                    121:  * Verify an RSA signature given a public key filename.
                    122:  *
                    123:  * We assume the signature is a signature of an MD5 hash, and therefore
                    124:  * the input to the signature had length MD5_DIGEST_LENGTH.
                    125:  */
                    126: int
                    127: rsa_util_verify(const char *pubkeyfile, const u_char *md5,
                    128:        const u_char *sig, size_t siglen)
                    129: {
                    130:        EVP_PKEY *pkey = NULL;
                    131:        RSA *rsa = NULL;
                    132:        BIO *bio = NULL;
                    133:        int match = 0;
                    134: 
                    135:        /* Read in public key */
                    136:        if ((bio = BIO_new(BIO_s_file())) == NULL) {
                    137:                ERR_print_errors_fp(stderr);
                    138:                goto done;
                    139:        }
                    140:        if (BIO_read_filename(bio, pubkeyfile) <= 0)
                    141:                goto done;
                    142:        if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) {
                    143:                ERR_print_errors_fp(stderr);
                    144:                goto done;
                    145:        }
                    146: 
                    147:        /* Get RSA public key */
                    148:        if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
                    149:                ERR_print_errors_fp(stderr);
                    150:                goto done;
                    151:        }
                    152: 
                    153:        /* Verify */
                    154:        match = rsa_util_verify_rsa(rsa, md5, sig, siglen);
                    155: 
                    156: done:
                    157:        /* Clean up */
                    158:        RSA_free(rsa);
                    159:        EVP_PKEY_free(pkey);
                    160:        BIO_free(bio);
                    161: 
                    162:        /* Return result */
                    163:        return (match);
                    164: }
                    165: 
                    166: /*
                    167:  * Verify an RSA signature given a private key filename.
                    168:  *
                    169:  * We assume the signature is a signature of an MD5 hash, and therefore
                    170:  * the input to the signature had length MD5_DIGEST_LENGTH.
                    171:  */
                    172: int
                    173: rsa_util_verify_priv(const char *privkeyfile, const u_char *md5,
                    174:        const u_char *sig, size_t siglen)
                    175: {
                    176:        FILE *fp = NULL;
                    177:        RSA *rsa = NULL;
                    178:        int match = 0;
                    179: 
                    180:        /* Open file */
                    181:        if ((fp = fopen(privkeyfile, "r")) == NULL) {
                    182:                fprintf(stderr, "%s: %s\n", privkeyfile, strerror(errno));
                    183:                goto done;
                    184:        }
                    185: 
                    186:        /* Read private key */
                    187:        if ((rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) {
                    188:                ERR_print_errors_fp(stderr);
                    189:                goto done;
                    190:        }
                    191:        ERR_clear_error();
                    192: 
                    193:        /* Verify */
                    194:        match = rsa_util_verify_rsa(rsa, md5, sig, siglen);
                    195: 
                    196: done:
                    197:        /* Clean up */
                    198:        RSA_free(rsa);
                    199:        if (fp != NULL)
                    200:                fclose(fp);
                    201: 
                    202:        /* Return result */
                    203:        return (match);
                    204: }
                    205: 
                    206: /*
                    207:  * Verify an RSA signature given an RSA public key.
                    208:  *
                    209:  * We assume the signature is a signature of an MD5 hash, and therefore
                    210:  * the input to the signature had length MD5_DIGEST_LENGTH.
                    211:  */
                    212: static int
                    213: rsa_util_verify_rsa(RSA *rsa, const u_char *md5,
                    214:        const u_char *sig, size_t siglen)
                    215: {
                    216:        u_char *vbuf = NULL;                    /* decrypted signature */
                    217:        int match = 0;
                    218:        int vlen;
                    219: 
                    220:        /* Decrypt using public key */
                    221:        if ((vbuf = MALLOC(TYPED_MEM_TEMP, MAX(siglen, RSA_size(rsa)))) == NULL)
                    222:                goto done;
                    223:        if ((vlen = RSA_public_decrypt(siglen,
                    224:            (u_char *)sig, vbuf, rsa, RSA_PKCS1_PADDING)) <= 0) {
                    225:                ERR_clear_error();
                    226:                goto done;
                    227:        }
                    228: 
                    229:        /* Compare decrypted signature with original hash value */
                    230:        if (vlen == MD5_DIGEST_LENGTH
                    231:            && memcmp(md5, vbuf, MD5_DIGEST_LENGTH) == 0)
                    232:                match = 1;
                    233: 
                    234: done:
                    235:        /* Clean up */
                    236:        FREE(TYPED_MEM_TEMP, vbuf);
                    237: 
                    238:        /* Return result */
                    239:        return (match);
                    240: }
                    241: 
                    242: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>