/* * Copyright (c) 2011-12 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include "ossl-config.h" #include #include #include #include "krb5-types.h" #include "rfc2459_asn1.h" #include "ossl-dsa.h" #include "ossl-common.h" /* #include "rk-roken.h" */ #ifdef HAVE_CDSA /* * */ #if 0 static int load_key(CSSM_CSP_HANDLE cspHandle, DSA *dsa, int use_public, CSSM_KEY_PTR key, size_t *keysize) { CSSM_KEY_SIZE keySize; CSSM_RETURN ret; size_t size; memset(key, 0, sizeof(*key)); if (use_public) { DSAPublicKey k; memset(&k, 0, sizeof(k)); ret = _cs_BN_to_integer(rsa->n, &k.modulus); if (ret == 0) { ret = _cs_BN_to_integer(rsa->e, &k.publicExponent); } if (ret) { free_RSAPublicKey(&k); return (0); } ASN1_MALLOC_ENCODE(RSAPublicKey, key->KeyData.Data, key->KeyData.Length, &k, &size, ret); free_RSAPublicKey(&k); if (ret) { return (1); } if (size != key->KeyData.Length) { abort(); } } else { RSAPrivateKey k; memset(&k, 0, sizeof(k)); k.version = 1; ret = _cs_BN_to_integer(rsa->n, &k.modulus); if (ret == 0) { ret = _cs_BN_to_integer(rsa->e, &k.publicExponent); } if (ret == 0) { ret = _cs_BN_to_integer(rsa->d, &k.privateExponent); } if (ret == 0) { ret = _cs_BN_to_integer(rsa->p, &k.prime1); } if (ret == 0) { ret = _cs_BN_to_integer(rsa->q, &k.prime2); } if (ret == 0) { ret = _cs_BN_to_integer(rsa->dmp1, &k.exponent1); } if (ret == 0) { ret = _cs_BN_to_integer(rsa->dmq1, &k.exponent2); } if (ret == 0) { ret = _cs_BN_to_integer(rsa->iqmp, &k.coefficient); } if (ret) { free_RSAPrivateKey(&k); return (1); } ASN1_MALLOC_ENCODE(RSAPrivateKey, key->KeyData.Data, key->KeyData.Length, &k, &size, ret); free_RSAPrivateKey(&k); if (ret) { return (1); } if (size != key->KeyData.Length) { abort(); } } key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW; key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA; key->KeyHeader.KeyClass = use_public ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY; key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; ret = CSSM_QueryKeySizeInBits(cspHandle, 0, key, &keySize); if (ret) { return (1); } key->KeyHeader.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; *keysize = (keySize.LogicalKeySizeInBits + 7) / 8; return (0); } static void unload_key(CSSM_KEY_PTR key) { free(key->KeyData.Data); memset(key, 0, sizeof(*key)); } typedef CSSM_RETURN (*op)(CSSM_CC_HANDLE, const CSSM_DATA *, uint32, CSSM_DATA_PTR, uint32, CSSM_SIZE *, CSSM_DATA_PTR); static int perform_rsa_op(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding, CSSM_ENCRYPT_MODE algMode, op func) { CSSM_CSP_HANDLE cspHandle = _cs_get_cdsa_csphandle(); CSSM_RETURN cret; CSSM_ACCESS_CREDENTIALS creds; CSSM_KEY cssmKey; CSSM_CC_HANDLE handle = 0; CSSM_DATA out, in, rem; int fret = 0; CSSM_SIZE outlen = 0; char remdata[1024]; size_t keysize; if (padding != RSA_PKCS1_PADDING) { return (-1); } memset(&creds, 0, sizeof(creds)); fret = load_key(cspHandle, rsa, (algMode == CSSM_ALGMODE_PUBLIC_KEY), &cssmKey, &keysize); if (fret) { return (-2); } fret = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA, &creds, &cssmKey, CSSM_PADDING_PKCS1, &handle); if (fret) { abort(); } { CSSM_CONTEXT_ATTRIBUTE attr; attr.AttributeType = CSSM_ATTRIBUTE_MODE; attr.AttributeLength = sizeof(attr.Attribute.Uint32); attr.Attribute.Uint32 = algMode; fret = CSSM_UpdateContextAttributes(handle, 1, &attr); if (fret) { abort(); } } in.Data = (uint8 *)from; in.Length = flen; out.Data = (uint8 *)to; out.Length = keysize; rem.Data = (uint8 *)remdata; rem.Length = sizeof(remdata); cret = func(handle, &in, 1, &out, 1, &outlen, &rem); if (cret) { /* cssmErrorString(cret); */ fret = -1; } else{ fret = outlen; } if (handle) { CSSM_DeleteContext(handle); } unload_key(&cssmKey); return (fret); } /* * */ static int cdsa_rsa_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { return (perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PUBLIC_KEY, CSSM_EncryptData)); } static int cdsa_rsa_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { return (perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PUBLIC_KEY, CSSM_DecryptData)); } static int cdsa_rsa_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { return (perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PRIVATE_KEY, CSSM_EncryptData)); } static int cdsa_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { return (perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PRIVATE_KEY, CSSM_DecryptData)); } static int cdsa_dsa_generate_key(DSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) { CSSM_CSP_HANDLE cspHandle = _cs_get_cdsa_csphandle(); uint32_t pubAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA; uint32_t privAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA; CSSM_CC_HANDLE handle = 0; CSSM_RETURN ret; size_t len; const unsigned char *p; CSSM_KEY priv_key, pub_key; AlgorithmIdentifier ai; memset(&priv_key, 0, sizeof(priv_key)); memset(&pub_key, 0, sizeof(pub_key)); memset(&ai, 0, sizeof(ai)); ret = CSSM_CSP_CreateKeyGenContext(cspHandle, CSSM_ALGID_DSA, bits, NULL, /* Seed */ NULL, /* Salt */ NULL, /* StartDate */ NULL, /* EndDate */ NULL, /* Params */ &handle); if (ret) { return (0); } { CSSM_CONTEXT_ATTRIBUTE attr; /* optional format specifiers */ attr.AttributeType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT; attr.AttributeLength = sizeof(attr.Attribute.Uint32); attr.Attribute.Uint32 = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; ret = CSSM_UpdateContextAttributes(handle, 1, &attr); if (ret) { abort(); } attr.AttributeType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT; ret = CSSM_UpdateContextAttributes(handle, 1, &attr); if (ret) { abort(); } } ret = CSSM_GenerateKeyPair(handle, /* pubkey */ CSSM_KEYUSE_DERIVE, pubAttr, &_cs_labelData, &pub_key, /* private key */ CSSM_KEYUSE_DERIVE, privAttr, &_cs_labelData, NULL, /* CredAndAclEntry */ &priv_key); CSSM_DeleteContext(handle); if (ret) { return (0); } ret = decode_AlgorithmIdentifier(priv_key.KeyData.Data, priv_key.KeyData.Length, &ai, NULL); if (ret || (ai.parameters == NULL)) { p = priv_key.KeyData.Data; len = priv_key.KeyData.Length; } else { p = ai.parameters->data; len = ai.parameters->length; } ret = (d2i_DSAPrivateKey(dsa, &p, len) == NULL) ? 0 : 1; free_AlgorithmIdentifier(&ai); CSSM_FreeKey(cspHandle, NULL, &pub_key, CSSM_FALSE); CSSM_FreeKey(cspHandle, NULL, &priv_key, CSSM_FALSE); return (ret); } #endif /* #if 0 */ static DSA_SIG * cdsa_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { return (NULL); } static int cdsa_dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { return (1); } static int cdsa_dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) { return (1); } static int cdsa_dsa_init(DSA *dsa) { return (1); } static int cdsa_dsa_finish(DSA *dsa) { return (1); } static int cdsa_dsa_paramgen(DSA *dsa, int bits, unsigned char *seed, int seed_len, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) { return (1); } static int cdsa_dsa_keygen(DSA *dsa) { return (1); } const DSA_METHOD _ossl_dsa_cdsa_method = { .name = "cryptoshim cdsa DSA", .dsa_do_sign = cdsa_dsa_do_sign, .dsa_sign_setup = cdsa_dsa_sign_setup, .dsa_do_verify = cdsa_dsa_do_verify, .init = cdsa_dsa_init, .finish = cdsa_dsa_finish, 0, NULL, .dsa_paramgen = cdsa_dsa_paramgen, .dsa_keygen = cdsa_dsa_keygen }; #endif /* HAVE_CDSA */ const DSA_METHOD * DSA_cdsa_method(void) { #ifdef HAVE_CDSA return (&_ossl_dsa_cdsa_method); #else return (NULL); #endif }