Annotation of embedaddon/libpdel/util/rsa_util.c, revision 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>