#if defined(BSAFE) || defined(DNSSAFE) static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/bsafe_link.c,v 1.12 2001/04/05 21:59:59 bwelling Exp $"; /* * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. * * Permission to use, copy modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. */ /* * This file contains two components * 1. Interface to the BSAFE library to allow compilation of Bind * with TIS/DNSSEC when BSAFE is not available * all calls to BSAFE are contained inside this file. * 2. The glue to connvert RSA KEYS to and from external formats */ #include "port_before.h" #include #include #include #include #include #include #include #include #include #include "dst_internal.h" # ifdef __STDC__ # define PROTOTYPES 1 # else # define PROTOTYPES 0 # endif # ifdef BSAFE # include # include # else # include # include # include # endif #include "port_after.h" typedef struct bsafekey { char *rk_signer; B_KEY_OBJ rk_Private_Key; B_KEY_OBJ rk_Public_Key; } RSA_Key; #ifndef MAX_RSA_MODULUS_BITS #define MAX_RSA_MODULUS_BITS 4096 #define MAX_RSA_MODULUS_LEN (MAX_RSA_MODULUS_BITS/8) #define MAX_RSA_PRIME_LEN (MAX_RSA_MODULUS_LEN/2) #endif #define NULL_SURRENDER (A_SURRENDER_CTX *)NULL_PTR #define NULL_RANDOM (B_ALGORITHM_OBJ)NULL_PTR B_ALGORITHM_METHOD *CHOOSER[] = { &AM_MD5, &AM_MD5_RANDOM, &AM_RSA_KEY_GEN, &AM_RSA_ENCRYPT, &AM_RSA_DECRYPT, &AM_RSA_CRT_ENCRYPT, &AM_RSA_CRT_DECRYPT, (B_ALGORITHM_METHOD *) NULL_PTR }; static u_char pkcs1[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; static int dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, const u_char *data, const int len, u_char *digest, const int digest_len); static int dst_bsafe_key_size(RSA_Key *r_key); static int dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, const u_char *data, const int len, u_char *signature, const int sig_len); static int dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, const u_char *data, const int len, const u_char *signature, const int sig_len); static int dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, const int out_len); static int dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, const int len); static int dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, const int buff_len); static int dst_bsafe_key_from_file_format(DST_KEY *d_key, const char *buff, const int buff_len); static int dst_bsafe_generate_keypair(DST_KEY *key, int exp); static int dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2); static void *dst_bsafe_free_key_structure(void *key); /* * dst_bsafe_init() Function to answer set up function pointers for * BSAFE/DNSSAFE related functions */ int dst_bsafe_init() { if (dst_t_func[KEY_RSA] != NULL) return (1); dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func)); if (dst_t_func[KEY_RSA] == NULL) return (0); memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func)); dst_t_func[KEY_RSA]->sign = dst_bsafe_sign; dst_t_func[KEY_RSA]->verify = dst_bsafe_verify; dst_t_func[KEY_RSA]->compare = dst_bsafe_compare_keys; dst_t_func[KEY_RSA]->generate = dst_bsafe_generate_keypair; dst_t_func[KEY_RSA]->destroy = dst_bsafe_free_key_structure; dst_t_func[KEY_RSA]->from_dns_key = dst_bsafe_from_dns_key; dst_t_func[KEY_RSA]->to_dns_key = dst_bsafe_to_dns_key; dst_t_func[KEY_RSA]->from_file_fmt = dst_bsafe_key_from_file_format; dst_t_func[KEY_RSA]->to_file_fmt = dst_bsafe_key_to_file_format; return (1); } /* * dst_bsafe_sign * Call BSAFE signing functions to sign a block of data. * There are three steps to signing, INIT (initialize structures), * UPDATE (hash (more) data), FINAL (generate a signature). This * routine performs one or more of these steps. * Parameters * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. * dkey structure holds context for a sign done in multiple calls. * context the context to use for this computation * data data to be signed. * len length in bytes of data. * priv_key key to use for signing. * signature location to store signature. * sig_len size in bytes of signature field. * returns * N Success on SIG_MODE_FINAL = returns signature length in bytes * 0 Success on SIG_MODE_INIT and UPDATE * <0 Failure */ static int dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, const u_char *data, const int len, u_char *signature, const int sig_len) { u_int sign_len = 0; int status = 0; B_ALGORITHM_OBJ *md5_ctx = NULL; int w_bytes = 0; u_int u_bytes = 0; u_char work_area[NS_MD5RSA_MAX_SIZE]; if (mode & SIG_MODE_INIT) { md5_ctx = (B_ALGORITHM_OBJ *) malloc(sizeof(B_ALGORITHM_OBJ)); if ((status = B_CreateAlgorithmObject(md5_ctx))) return (-1); if ((status = B_SetAlgorithmInfo(*md5_ctx, AI_MD5, NULL))) return (-1); } else if (context) md5_ctx = (B_ALGORITHM_OBJ *) *context; if (md5_ctx == NULL) return (-1); w_bytes = dst_bsafe_md5digest(mode, md5_ctx, data, len,work_area, sizeof(work_area)); if (w_bytes < 0 || (mode & SIG_MODE_FINAL)) { B_DestroyAlgorithmObject(md5_ctx); SAFE_FREE(md5_ctx); if (w_bytes < 0) return (w_bytes); } if (mode & SIG_MODE_FINAL) { RSA_Key *key; int ret = 0; B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ) NULL_PTR; if (dkey == NULL || dkey->dk_KEY_struct == NULL) return (-1); key = (RSA_Key *) dkey->dk_KEY_struct; if (key == NULL || key->rk_Private_Key == NULL) return (-1); if ((status = B_CreateAlgorithmObject(&rsaEncryptor))) return (SIGN_FINAL_FAILURE); if ((status = B_SetAlgorithmInfo(rsaEncryptor, AI_PKCS_RSAPrivate, NULL_PTR))) ret = SIGN_FINAL_FAILURE; if (ret == 0 && (status = B_EncryptInit(rsaEncryptor, key->rk_Private_Key, CHOOSER, NULL_SURRENDER))) ret = SIGN_FINAL_FAILURE; if (ret == 0 && (status = B_EncryptUpdate(rsaEncryptor, signature, &u_bytes, sig_len, pkcs1, sizeof(pkcs1), NULL_PTR, NULL_SURRENDER))) ret = SIGN_FINAL_FAILURE; if (ret == 0 && (status = B_EncryptUpdate(rsaEncryptor, signature, &u_bytes, sig_len, work_area, w_bytes, NULL_PTR, NULL_SURRENDER))) ret = SIGN_FINAL_FAILURE; if (ret == 0 && (status = B_EncryptFinal(rsaEncryptor, signature + u_bytes, &sign_len, sig_len - u_bytes, NULL_PTR, NULL_SURRENDER))) ret = SIGN_FINAL_FAILURE; B_DestroyAlgorithmObject(&rsaEncryptor); if (ret != 0) return (ret); } else { if (context == NULL) return (-1); *context = (void *) md5_ctx; } return (sign_len); } /* * Dst_bsafe_verify * Calls BSAFE verification routines. There are three steps to * verification, INIT (initialize structures), UPDATE (hash (more) data), * FINAL (generate a signature). This routine performs one or more of * these steps. * Parameters * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. * dkey structure holds context for a verify done in multiple calls. * context the context to use for this computation * data data signed. * len length in bytes of data. * pub_key key to use for verify. * signature signature. * sig_len length in bytes of signature. * returns * 0 Success * <0 Failure */ static int dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, const u_char *data, const int len, const u_char *signature, const int sig_len) { B_ALGORITHM_OBJ *md5_ctx = NULL; u_char digest[DST_HASH_SIZE]; u_char work_area[DST_HASH_SIZE + sizeof(pkcs1)]; int status = 0, w_bytes = 0; u_int u_bytes = 0; if (mode & SIG_MODE_INIT) { md5_ctx = (B_ALGORITHM_OBJ *) malloc(sizeof(B_ALGORITHM_OBJ)); if ((status = B_CreateAlgorithmObject(md5_ctx))) return (-1); if ((status = B_SetAlgorithmInfo(*md5_ctx, AI_MD5, NULL))) return (-1); } else if (context) md5_ctx = (B_ALGORITHM_OBJ *) *context; if (md5_ctx == NULL) return (-1); w_bytes = dst_bsafe_md5digest(mode, md5_ctx, data, len, digest, sizeof(digest)); if (w_bytes < 0 || (mode & SIG_MODE_FINAL)) { B_DestroyAlgorithmObject(md5_ctx); SAFE_FREE(md5_ctx); if (w_bytes < 0) return (-1); } if (mode & SIG_MODE_FINAL) { RSA_Key *key; int ret = 0; B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ) NULL_PTR; if (dkey == NULL || dkey->dk_KEY_struct == NULL) return (-1); key = (RSA_Key *) dkey->dk_KEY_struct; if (key->rk_Public_Key == NULL) return (-2); if (rsaEncryptor == NULL_PTR) { if ((status = B_CreateAlgorithmObject(&rsaEncryptor))) ret = SIGN_FINAL_FAILURE; if (ret == 0 && (status = B_SetAlgorithmInfo(rsaEncryptor, AI_PKCS_RSAPublic, NULL_PTR))) ret = VERIFY_FINAL_FAILURE; } if (ret == 0 && (status = B_DecryptInit(rsaEncryptor, key->rk_Public_Key, CHOOSER, NULL_SURRENDER))) ret = VERIFY_FINAL_FAILURE; if (ret == 0 && (status = B_DecryptUpdate(rsaEncryptor, work_area, &u_bytes, 0, (u_char *) signature, sig_len, NULL_PTR, NULL_SURRENDER))) ret = VERIFY_FINAL_FAILURE; if (ret == 0 && (status = B_DecryptFinal(rsaEncryptor, work_area + u_bytes, &u_bytes, sizeof(work_area) - u_bytes, NULL_PTR, NULL_SURRENDER))) ret = VERIFY_FINAL_FAILURE; B_DestroyAlgorithmObject(&rsaEncryptor); /* skip PKCS#1 header in output from Decrypt function */ if (ret) return (ret); ret = memcmp(digest, &work_area[sizeof(pkcs1)], w_bytes); if (ret == 0) return(0); else return(VERIFY_FINAL_FAILURE); } else { if (context == NULL) return (-1); *context = (void *) md5_ctx; } return (0); } /* * dst_bsafe_to_dns_key * Converts key from RSA to DNS distribution format * This function gets in a pointer to the public key and a work area * to write the key into. * Parameters * public KEY structure * out_str buffer to write encoded key into * out_len size of out_str * Return * N >= 0 length of encoded key * n < 0 error */ static int dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, const int out_len) { B_KEY_OBJ public; A_RSA_KEY *pub = NULL; u_char *op = out_str; int n = 0; if (in_key == NULL || in_key->dk_KEY_struct == NULL || out_len <= 0 || out_str == NULL) return (-1); public = (B_KEY_OBJ)((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key; n = B_GetKeyInfo((POINTER *) &pub, public, KI_RSAPublic); if (out_len < pub->exponent.len) /* not enough space */ return (-1); if (pub->exponent.len < 256) /* key exponent is <= 2040 bits */ *op++ = (u_int8_t) pub->exponent.len; else { /* key exponent is > 2040 bits */ u_int16_t e = (u_int16_t) pub->exponent.len; *op++ = 0; /* 3 byte lenght field */ dst_s_put_int16(op, e); op += sizeof(e); n = 2; } n += pub->exponent.len; memcpy(op, pub->exponent.data, n); op += n; n++; if ((out_len - n) > pub->modulus.len) { /*copy exponent */ memcpy(op, pub->modulus.data, pub->modulus.len); n += pub->modulus.len; } else n = -1; return (n); } /* * dst_bsafe_from_dns_key * Converts from a DNS KEY RR format to an RSA KEY. * Parameters * len Length in bytes of DNS key * key DNS key * name Key name * s_key DST structure that will point to the RSA key this routine * will build. * Return * 0 The input key, s_key or name was null. * 1 Success */ static int dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) { int bytes; const u_char *key_ptr; RSA_Key *r_key; A_RSA_KEY *public; if (s_key == NULL || len < 0 || key == NULL) return (0); r_key = (RSA_Key *) s_key->dk_KEY_struct; if (r_key != NULL) /* do not reuse */ s_key->dk_func->destroy(r_key); if (len == 0) return (1); if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { EREPORT(("dst_bsafe_from_dns_key(): Memory allocation error 1")); return (0); } memset(r_key, 0, sizeof(RSA_Key)); s_key->dk_KEY_struct = (void *) r_key; r_key->rk_signer = strdup(s_key->dk_key_name); if (B_CreateKeyObject(&r_key->rk_Public_Key) != 0) { EREPORT(("dst_bsafe_from_dns_key(): Memory allocation error 3")); s_key->dk_func->destroy(r_key); return (0); } key_ptr = key; bytes = (int) *key_ptr++; /* length of exponent in bytes */ if (bytes == 0) { /* special case for long exponents */ bytes = (int) dst_s_get_int16(key_ptr); key_ptr += sizeof(u_int16_t); } if (bytes > MAX_RSA_MODULUS_LEN) { dst_bsafe_free_key_structure(r_key); return (-1); } if ((public = (A_RSA_KEY *) malloc(sizeof(A_RSA_KEY))) == NULL) return (0); memset(public, 0, sizeof(*public)); public->exponent.len = bytes; if ((public->exponent.data = (u_char *) malloc(bytes)) == NULL) return (0); memcpy(public->exponent.data, key_ptr, bytes); key_ptr += bytes; /* beginning of modulus */ bytes = len - bytes - 1; /* length of modulus */ if (bytes > MAX_RSA_MODULUS_LEN) { dst_bsafe_free_key_structure(r_key); return (-1); } public->modulus.len = bytes; if ((public->modulus.data = (u_char *) malloc(bytes)) == NULL) return (0); memcpy(public->modulus.data, key_ptr, bytes); B_SetKeyInfo(r_key->rk_Public_Key, KI_RSAPublic, (POINTER) public); s_key->dk_key_size = dst_bsafe_key_size(r_key); SAFE_FREE(public->modulus.data); SAFE_FREE(public->exponent.data); SAFE_FREE(public); return (1); } /* * dst_bsafe_key_to_file_format * Encodes an RSA Key into the portable file format. * Parameters * rkey RSA KEY structure * buff output buffer * buff_len size of output buffer * Return * 0 Failure - null input rkey * -1 Failure - not enough space in output area * N Success - Length of data returned in buff */ static int dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, const int buff_len) { char *bp; int len, b_len; B_KEY_OBJ rkey; A_PKCS_RSA_PRIVATE_KEY *private = NULL; if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ return (0); if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) return (-1); /* no OR not enough space in output area */ rkey = (B_KEY_OBJ)((RSA_Key *) key->dk_KEY_struct)->rk_Private_Key; B_GetKeyInfo((POINTER *) &private, rkey, KI_PKCS_RSAPrivate); memset(buff, 0, buff_len); /* just in case */ /* write file header */ sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA"); bp = strchr(buff, '\0'); b_len = buff_len - (bp - buff); if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ", private->modulus.data, private->modulus.len)) <= 0) return (-1); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ", private->publicExponent.data, private->publicExponent.len)) <= 0) return (-2); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ", private->privateExponent.data, private->privateExponent.len)) <= 0) return (-3); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ", private->prime[0].data, private->prime[0].len)) < 0) return (-4); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ", private->prime[1].data, private->prime[1].len)) < 0) return (-5); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ", private->primeExponent[0].data, private->primeExponent[0].len)) < 0) return (-6); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ", private->primeExponent[1].data, private->primeExponent[1].len)) < 0) return (-7); bp += len; b_len -= len; if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ", private->coefficient.data, private->coefficient.len)) < 0) return (-8); bp += len; b_len -= len; return (buff_len - b_len); } /* * dst_bsafe_key_from_file_format * Converts contents of a private key file into a private RSA key. * Parameters * RSA_Key structure to put key into * buff buffer containing the encoded key * buff_len the length of the buffer * Return * n >= 0 Foot print of the key converted * n < 0 Error in conversion */ static int dst_bsafe_key_from_file_format(DST_KEY *d_key, const char *buff, const int buff_len) { int status; char s[RAW_KEY_SIZE]; int len, s_len = sizeof(s); int tag = -1; const char *p = buff; RSA_Key *b_key; A_RSA_KEY *public; A_PKCS_RSA_PRIVATE_KEY *private; if (d_key == NULL || buff == NULL || buff_len <= 0) return (-1); b_key = (RSA_Key *) malloc(sizeof(RSA_Key)); public = (A_RSA_KEY *) malloc(sizeof(A_RSA_KEY)); private = (A_PKCS_RSA_PRIVATE_KEY *) malloc(sizeof(A_PKCS_RSA_PRIVATE_KEY)); if (b_key == NULL || private == NULL || public == NULL) { SAFE_FREE(b_key); SAFE_FREE(public); SAFE_FREE(private); return (-2); } memset(b_key, 0, sizeof(*b_key)); memset(public, 0, sizeof(A_RSA_KEY)); memset(private, 0, sizeof(A_PKCS_RSA_PRIVATE_KEY)); d_key->dk_KEY_struct = (void *) b_key; if (!dst_s_verify_str(&p, "Modulus: ")) return (-3); memset(s, 0, s_len); if ((len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len)) == 0) return (-4); private->modulus.len = len; if ((private->modulus.data = malloc(len)) == NULL) return (-5); memcpy(private->modulus.data, s + s_len - len, len); while (*(++p) && p < (const char *) &buff[buff_len]) { if (dst_s_verify_str(&p, "PublicExponent: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len))) return (-5); private->publicExponent.len = len; if ((private->publicExponent.data = malloc(len)) == NULL) return (-6); memcpy(private->publicExponent.data, s + s_len - len, len); } else if (dst_s_verify_str(&p, "PrivateExponent: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len))) return (-6); private->privateExponent.len = len; if ((private->privateExponent.data = malloc(len)) == NULL) return (-7); memcpy(private->privateExponent.data, s + s_len - len, len); } else if (dst_s_verify_str(&p, "Prime1: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, MAX_RSA_PRIME_LEN))) return (-7); private->prime[0].len = len; if ((private->prime[0].data = malloc(len)) == NULL) return (-8); memcpy(private->prime[0].data, s + MAX_RSA_PRIME_LEN - len, len); } else if (dst_s_verify_str(&p, "Prime2: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, MAX_RSA_PRIME_LEN))) return (-8); private->prime[1].len = len; if ((private->prime[1].data = malloc(len)) == NULL) return (-9); memcpy(private->prime[1].data, s + MAX_RSA_PRIME_LEN - len, len); } else if (dst_s_verify_str(&p, "Exponent1: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, MAX_RSA_PRIME_LEN))) return (-9); private->primeExponent[0].len = len; if ((private->primeExponent[0].data = malloc(len)) == NULL) return (-10); memcpy(private->primeExponent[0].data, s + MAX_RSA_PRIME_LEN - len, len); } else if (dst_s_verify_str(&p, "Exponent2: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, MAX_RSA_PRIME_LEN))) return (-10); private->primeExponent[1].len = len; if ((private->primeExponent[1].data = malloc(len)) == NULL) return (-11); memcpy(private->primeExponent[1].data, s + MAX_RSA_PRIME_LEN - len, len); } else if (dst_s_verify_str(&p, "Coefficient: ")) { if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, MAX_RSA_PRIME_LEN))) return (-11); private->coefficient.len = len; if ((private->coefficient.data = malloc(len)) == NULL) return (-12); memcpy(private->coefficient.data, s + MAX_RSA_PRIME_LEN - len, len); } else { EREPORT(("Decode_RSAKey(): Bad keyword %s\n", p)); return (-12); } } /* while p */ public->modulus.len = private->modulus.len; if ((public->modulus.data = (u_char *) malloc(public->modulus.len)) == NULL) return (-13); memcpy(public->modulus.data, private->modulus.data, private->modulus.len); public->exponent.len = private->publicExponent.len; if ((public->exponent.data = (u_char *) malloc(public->exponent.len)) == NULL) return (-14); memcpy(public->exponent.data, private->publicExponent.data, private->publicExponent.len); status = B_CreateKeyObject(&(b_key->rk_Public_Key)); if (status) return (-1); status = B_SetKeyInfo(b_key->rk_Public_Key, KI_RSAPublic, (POINTER) public); if (status) return (-1); status = B_CreateKeyObject(&b_key->rk_Private_Key); if (status) return (-1); status = B_SetKeyInfo(b_key->rk_Private_Key, KI_PKCS_RSAPrivate, (POINTER) private); if (status) return (-1); d_key->dk_key_size = dst_bsafe_key_size(b_key); SAFE_FREE(private->modulus.data); SAFE_FREE(private->publicExponent.data); SAFE_FREE(private->privateExponent.data); SAFE_FREE(private->prime[0].data); SAFE_FREE(private->prime[1].data); SAFE_FREE(private->primeExponent[0].data); SAFE_FREE(private->primeExponent[1].data); SAFE_FREE(private->coefficient.data); SAFE_FREE(private); /* is this the right thing to do ??? XXXX */ SAFE_FREE(public->modulus.data); SAFE_FREE(public->exponent.data); SAFE_FREE(public); return (0); } /* * dst_bsafe_free_key_structure * Frees all dynamicly allocated structures in RSA_Key. */ static void * dst_bsafe_free_key_structure(void *key) { RSA_Key *r_key = (RSA_Key *) key; if (r_key != NULL) { if (r_key->rk_Private_Key) B_DestroyKeyObject(&r_key->rk_Private_Key); if (r_key->rk_Public_Key) B_DestroyKeyObject(&r_key->rk_Public_Key); SAFE_FREE2(r_key->rk_signer, strlen(r_key->rk_signer)); SAFE_FREE(r_key); } return (NULL); } /* * dst_bsafe_generate_keypair * Generates unique keys that are hard to predict. * Parameters * key generic Key structure * exp the public exponent * Return * 0 Failure * 1 Success */ static int dst_bsafe_generate_keypair(DST_KEY *key, int exp) { int i, status; B_KEY_OBJ private; B_KEY_OBJ public; B_ALGORITHM_OBJ keypairGenerator; B_ALGORITHM_OBJ randomAlgorithm; A_RSA_KEY_GEN_PARAMS keygenParams; char exponent[4]; int exponent_len; RSA_Key *rsa; POINTER randomSeed = NULL_PTR; int randomSeedLen; A_RSA_KEY *pk_access = NULL; if (key == NULL || key->dk_alg != KEY_RSA) return (0); if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { EREPORT(("dst_bsafe_generate_keypair: Memory allocation error 3")); return (0); } memset(rsa, 0, sizeof(*rsa)); if ((status = B_CreateAlgorithmObject(&keypairGenerator)) != 0) return (0); keygenParams.modulusBits = key->dk_key_size; /* exp = 0 or 1 are special (mean 3 or F4) */ if (exp == 0) exp = 3; else if (exp == 1) exp = 65537; /* Now encode the exponent and its length */ if (exp < 256) { exponent_len = 1; exponent[0] = exp; } else if (exp < (1 << 16)) { exponent_len = 2; exponent[0] = exp >> 8; exponent[1] = exp; } else if (exp < (1 << 24)) { exponent_len = 3; exponent[0] = exp >> 16; exponent[1] = exp >> 8; exponent[2] = exp; } else { exponent_len = 4; exponent[0] = exp >> 24; exponent[1] = exp >> 16; exponent[2] = exp >> 8; exponent[3] = exp; } if ((keygenParams.publicExponent.data = (u_char *) malloc(exponent_len)) == NULL) return (0); memcpy(keygenParams.publicExponent.data, exponent, exponent_len); keygenParams.publicExponent.len = exponent_len; if ((status = B_SetAlgorithmInfo (keypairGenerator, AI_RSAKeyGen, (POINTER) &keygenParams)) != 0) return (0); if ((status = B_GenerateInit(keypairGenerator, CHOOSER, NULL_SURRENDER)) != 0) return (0); if ((status = B_CreateKeyObject(&public)) != 0) return (0); if ((status = B_CreateKeyObject(&private)) != 0) return (0); if ((status = B_CreateAlgorithmObject(&randomAlgorithm)) != 0) return (0); if ((status = B_SetAlgorithmInfo(randomAlgorithm, AI_MD5Random, NULL_PTR)) != 0) return (0); if ((status = B_RandomInit(randomAlgorithm, CHOOSER, NULL_SURRENDER)) != 0) return (0); randomSeedLen = 256; if ((randomSeed = malloc(randomSeedLen)) == NULL) return (0); if ((status = (randomSeed == NULL_PTR)) != 0) return (0); /* gets random seed from /dev/random if present, generates random * values if it is not present. * first fill the buffer with semi random data * then fill as much as possible with good random data */ i = dst_random(DST_RAND_SEMI, randomSeedLen, randomSeed); i += dst_random(DST_RAND_KEY, randomSeedLen, randomSeed); if (i <= randomSeedLen) { SAFE_FREE(rsa); return(0); } if ((status = B_RandomUpdate(randomAlgorithm, randomSeed, randomSeedLen, NULL_SURRENDER)) != 0) { SAFE_FREE(rsa); return (0); } SAFE_FREE2(randomSeed, randomSeedLen); if ((status = B_GenerateKeypair(keypairGenerator, public, private, randomAlgorithm, NULL_SURRENDER)) != 0) { SAFE_FREE(rsa); return (0); } rsa->rk_signer = strdup(key->dk_key_name); rsa->rk_Private_Key = private; rsa->rk_Public_Key = public; key->dk_KEY_struct = (void *) rsa; B_GetKeyInfo((POINTER *) &pk_access, public, KI_RSAPublic); return (1); } /************************************************************************** * dst_bsafe_compare_keys * Compare two keys for equality. * Return * 0 The keys are equal * NON-ZERO The keys are not equal */ static int dst_s_bsafe_itemcmp(ITEM i1, ITEM i2) { if (i1.len != i2.len || memcmp (i1.data, i2.data, i1.len)) return (1); else return (0); } static int dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2) { int status, s1 = 0, s2 = 0; RSA_Key *rkey1 = (RSA_Key *) key1->dk_KEY_struct; RSA_Key *rkey2 = (RSA_Key *) key2->dk_KEY_struct; A_RSA_KEY *public1 = NULL, *public2 = NULL; A_PKCS_RSA_PRIVATE_KEY *p1 = NULL, *p2 = NULL; if (rkey1 == NULL && rkey2 == NULL) return(0); else if (rkey1 == NULL) return (1); else if (rkey2 == NULL) return (2); if (rkey1->rk_Public_Key) B_GetKeyInfo((POINTER *) &public1, rkey1->rk_Public_Key, KI_RSAPublic); if (rkey2->rk_Public_Key) B_GetKeyInfo((POINTER *) &public2, rkey2->rk_Public_Key, KI_RSAPublic); if (public1 == NULL && public2 == NULL) return (0); else if (public1 == NULL || public2 == NULL) return (1); status = dst_s_bsafe_itemcmp(public1->modulus, public2->modulus) || dst_s_bsafe_itemcmp(public1->exponent, public2->exponent); if (status) return (status); if (rkey1->rk_Private_Key == NULL || rkey2->rk_Private_Key == NULL) /* if neither or only one is private key consider identical */ return (status); if (rkey1->rk_Private_Key) s1 = B_GetKeyInfo((POINTER *) &p1, rkey1->rk_Private_Key, KI_PKCS_RSAPrivate); if (rkey2->rk_Private_Key) s2 = B_GetKeyInfo((POINTER *) &p2, rkey2->rk_Private_Key, KI_PKCS_RSAPrivate); if (p1 == NULL || p2 == NULL) return (0); status = dst_s_bsafe_itemcmp(p1->modulus, p2->modulus) || dst_s_bsafe_itemcmp (p1->publicExponent, p2->publicExponent) || dst_s_bsafe_itemcmp (p1->privateExponent, p2->privateExponent) || dst_s_bsafe_itemcmp (p1->prime[0], p2->prime[0]) || dst_s_bsafe_itemcmp (p1->prime[1], p2->prime[1]) || dst_s_bsafe_itemcmp (p1->primeExponent[0], p2->primeExponent[0])|| dst_s_bsafe_itemcmp (p1->primeExponent[1], p2->primeExponent[1])|| dst_s_bsafe_itemcmp (p1->coefficient, p2->coefficient); return (status); } /* * dst_bsafe_key_size() * Function to calculate how the size of the key in bits */ static int dst_bsafe_key_size(RSA_Key *r_key) { int size; A_PKCS_RSA_PRIVATE_KEY *private = NULL; if (r_key == NULL) return (-1); if (r_key->rk_Private_Key) B_GetKeyInfo((POINTER *) &private, r_key->rk_Private_Key, KI_PKCS_RSAPrivate); else if (r_key->rk_Public_Key) B_GetKeyInfo((POINTER *) &private, r_key->rk_Public_Key, KI_RSAPublic); size = dst_s_calculate_bits(private->modulus.data, private->modulus.len * 8); return (size); } /* * dst_bsafe_md5digest(): function to digest data using MD5 digest function * if needed */ static int dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, const u_char *data, const int len, u_char *digest, const int digest_len) { int status = 0; u_int work_size = 0; if (digest_obj == NULL || *digest_obj == NULL) { printf("NO digest obj\n"); exit(-33); } if ((mode & SIG_MODE_INIT) && (status = B_DigestInit(*digest_obj, (B_KEY_OBJ) NULL, CHOOSER, NULL_SURRENDER))) return (SIGN_INIT_FAILURE); if ((mode & SIG_MODE_UPDATE) && data && (len > 0) && (status = B_DigestUpdate(*digest_obj, (u_char *) data, len, NULL_SURRENDER))) return (SIGN_UPDATE_FAILURE); if (mode & SIG_MODE_FINAL) { if (digest == NULL || (status = B_DigestFinal(*digest_obj, digest, &work_size, digest_len, NULL_SURRENDER))) return (SIGN_FINAL_FAILURE); return (work_size); } return (0); } /* * just use the standard memory functions for bsafe */ void T_free(POINTER block) { free(block); } POINTER T_malloc(unsigned int len) { return (malloc(len)); } int T_memcmp(POINTER firstBlock, POINTER secondBlock, unsigned int len) { return (memcmp(firstBlock, secondBlock, len)); } void T_memcpy(POINTER output, POINTER input, unsigned int len) { memcpy(output, input, len); } void T_memmove(POINTER output, POINTER input, unsigned int len) { memmove(output, input, len); } void T_memset(POINTER output, int value, unsigned int len) { memset(output, value, len); } POINTER T_realloc(POINTER block, unsigned int len) { return (realloc(block, len)); } #else /* BSAFE NOT available */ int dst_bsafe_init() { return (0); } #endif /* BSAFE */