1/* 2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <config.h> 37 38#include <stdio.h> 39#include <stdlib.h> 40#include <krb5-types.h> 41#include <assert.h> 42 43#include <rsa.h> 44 45#ifdef HAVE_CDSA 46#define NEED_CDSA 1 47 48#include <rfc2459_asn1.h> 49 50#include "common.h" 51 52#include <roken.h> 53 54/* 55 * 56 */ 57 58 59static int 60load_key(CSSM_CSP_HANDLE cspHandle, RSA *rsa, int use_public, CSSM_KEY_PTR key, size_t *keysize) 61{ 62 CSSM_KEY_SIZE keySize; 63 CSSM_RETURN ret; 64 size_t size; 65 66 memset(key, 0, sizeof(*key)); 67 68 if (use_public) { 69 RSAPublicKey k; 70 71 memset(&k, 0, sizeof(k)); 72 73 ret = _hc_BN_to_integer(rsa->n, &k.modulus); 74 if (ret == 0) 75 ret = _hc_BN_to_integer(rsa->e, &k.publicExponent); 76 if (ret) { 77 free_RSAPublicKey(&k); 78 return 0; 79 } 80 81 ASN1_MALLOC_ENCODE(RSAPublicKey, key->KeyData.Data, key->KeyData.Length, 82 &k, &size, ret); 83 free_RSAPublicKey(&k); 84 if (ret) 85 return 1; 86 if (size != key->KeyData.Length) 87 abort(); 88 89 } else { 90 RSAPrivateKey k; 91 92 memset(&k, 0, sizeof(k)); 93 94 k.version = 1; 95 ret = _hc_BN_to_integer(rsa->n, &k.modulus); 96 if (ret == 0) 97 ret = _hc_BN_to_integer(rsa->e, &k.publicExponent); 98 if (ret == 0) 99 ret = _hc_BN_to_integer(rsa->d, &k.privateExponent); 100 if (ret == 0) 101 ret = _hc_BN_to_integer(rsa->p, &k.prime1); 102 if (ret == 0) 103 ret = _hc_BN_to_integer(rsa->q, &k.prime2); 104 if (ret == 0) 105 ret = _hc_BN_to_integer(rsa->dmp1, &k.exponent1); 106 if (ret == 0) 107 ret = _hc_BN_to_integer(rsa->dmq1, &k.exponent2); 108 if (ret == 0) 109 ret = _hc_BN_to_integer(rsa->iqmp, &k.coefficient); 110 if (ret) { 111 free_RSAPrivateKey(&k); 112 return 1; 113 } 114 115 ASN1_MALLOC_ENCODE(RSAPrivateKey, key->KeyData.Data, key->KeyData.Length, 116 &k, &size, ret); 117 free_RSAPrivateKey(&k); 118 if (ret) 119 return 1; 120 if (size != key->KeyData.Length) 121 abort(); 122 } 123 124 key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; 125 key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW; 126 key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; 127 key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA; 128 key->KeyHeader.KeyClass = use_public ? 129 CSSM_KEYCLASS_PUBLIC_KEY : 130 CSSM_KEYCLASS_PRIVATE_KEY; 131 key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; 132 key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; 133 134 ret = CSSM_QueryKeySizeInBits(cspHandle, 0, key, &keySize); 135 if(ret) 136 return 1; 137 138 key->KeyHeader.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; 139 140 *keysize = (keySize.LogicalKeySizeInBits + 7) / 8; 141 142 return 0; 143} 144 145static void 146unload_key(CSSM_KEY_PTR key) 147{ 148 free(key->KeyData.Data); 149 memset(key, 0, sizeof(*key)); 150} 151 152typedef CSSM_RETURN (*op)(CSSM_CC_HANDLE, const CSSM_DATA *, 153 uint32, CSSM_DATA_PTR, uint32, 154 CSSM_SIZE *, CSSM_DATA_PTR); 155 156 157static int 158perform_rsa_op(int flen, const unsigned char* from, 159 unsigned char* to, RSA* rsa, int padding, 160 CSSM_ENCRYPT_MODE algMode, op func) 161{ 162 CSSM_CSP_HANDLE cspHandle = _hc_get_cdsa_csphandle(); 163 CSSM_RETURN cret; 164 CSSM_ACCESS_CREDENTIALS creds; 165 CSSM_KEY cssmKey; 166 CSSM_CC_HANDLE handle = 0; 167 CSSM_DATA out, in, rem; 168 int fret = 0; 169 CSSM_SIZE outlen = 0; 170 char remdata[1024]; 171 size_t keysize; 172 173 if (padding != RSA_PKCS1_PADDING) 174 return -1; 175 176 memset(&creds, 0, sizeof(creds)); 177 178 fret = load_key(cspHandle, rsa, (algMode == CSSM_ALGMODE_PUBLIC_KEY), 179 &cssmKey, &keysize); 180 if (fret) 181 return -2; 182 183 fret = CSSM_CSP_CreateAsymmetricContext(cspHandle, 184 CSSM_ALGID_RSA, 185 &creds, 186 &cssmKey, 187 CSSM_PADDING_PKCS1, 188 &handle); 189 if(fret) abort(); 190 191 { 192 CSSM_CONTEXT_ATTRIBUTE attr; 193 194 attr.AttributeType = CSSM_ATTRIBUTE_MODE; 195 attr.AttributeLength = sizeof(attr.Attribute.Uint32); 196 attr.Attribute.Uint32 = algMode; 197 198 fret = CSSM_UpdateContextAttributes(handle, 1, &attr); 199 if (fret) abort(); 200 } 201 202 in.Data = (uint8 *)from; 203 in.Length = flen; 204 205 out.Data = (uint8 *)to; 206 out.Length = keysize; 207 208 rem.Data = (uint8 *)remdata; 209 rem.Length = sizeof(remdata); 210 211 cret = func(handle, &in, 1, &out, 1, &outlen, &rem); 212 if(cret) { 213 /* cssmErrorString(cret); */ 214 fret = -1; 215 } else 216 fret = outlen; 217 218 if(handle) 219 CSSM_DeleteContext(handle); 220 unload_key(&cssmKey); 221 222 return fret; 223} 224 225/* 226 * 227 */ 228 229 230static int 231cdsa_rsa_public_encrypt(int flen, const unsigned char* from, 232 unsigned char* to, RSA* rsa, int padding) 233{ 234 return perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PUBLIC_KEY, CSSM_EncryptData); 235} 236 237static int 238cdsa_rsa_public_decrypt(int flen, const unsigned char* from, 239 unsigned char* to, RSA* rsa, int padding) 240{ 241 return perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PUBLIC_KEY, CSSM_DecryptData); 242} 243 244static int 245cdsa_rsa_private_encrypt(int flen, const unsigned char* from, 246 unsigned char* to, RSA* rsa, int padding) 247{ 248 return perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PRIVATE_KEY, CSSM_EncryptData); 249} 250 251static int 252cdsa_rsa_private_decrypt(int flen, const unsigned char* from, 253 unsigned char* to, RSA* rsa, int padding) 254{ 255 return perform_rsa_op(flen, from, to, rsa, padding, CSSM_ALGMODE_PRIVATE_KEY, CSSM_DecryptData); 256} 257 258 259static int 260cdsa_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) 261{ 262 CSSM_CSP_HANDLE cspHandle = _hc_get_cdsa_csphandle(); 263 uint32_t pubAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA; 264 uint32_t privAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA; 265 CSSM_CC_HANDLE handle; 266 CSSM_RETURN ret; 267 size_t len; 268 const unsigned char *p; 269 CSSM_KEY priv_key, pub_key; 270 AlgorithmIdentifier ai; 271 272 memset(&priv_key, 0, sizeof(priv_key)); 273 memset(&pub_key, 0, sizeof(pub_key)); 274 memset(&ai, 0, sizeof(ai)); 275 276 ret = CSSM_CSP_CreateKeyGenContext(cspHandle, 277 CSSM_ALGID_RSA, 278 bits, 279 NULL, 280 NULL, 281 NULL, 282 NULL, 283 NULL, 284 &handle); 285 if (ret) 286 return 0; 287 288 { 289 CSSM_CONTEXT_ATTRIBUTE attr; 290 291 attr.AttributeType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT; 292 attr.AttributeLength = sizeof(attr.Attribute.Uint32); 293 attr.Attribute.Uint32 = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; 294 295 ret = CSSM_UpdateContextAttributes(handle, 1, &attr); 296 if (ret) abort(); 297 298 attr.AttributeType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT; 299 ret = CSSM_UpdateContextAttributes(handle, 1, &attr); 300 if (ret) abort(); 301 } 302 303 ret = CSSM_GenerateKeyPair(handle, 304 /* pubkey */ 305 CSSM_KEYUSE_DERIVE, 306 pubAttr, 307 &_hc_labelData, 308 &pub_key, 309 /* private key */ 310 CSSM_KEYUSE_DERIVE, 311 privAttr, 312 &_hc_labelData, 313 NULL, 314 &priv_key); 315 316 CSSM_DeleteContext(handle); 317 if (ret) 318 return 0; 319 320 ret = decode_AlgorithmIdentifier(priv_key.KeyData.Data, 321 priv_key.KeyData.Length, &ai, NULL); 322 if (ret || ai.parameters == NULL) { 323 p = priv_key.KeyData.Data; 324 len = priv_key.KeyData.Length; 325 } else { 326 p = ai.parameters->data; 327 len = ai.parameters->length; 328 } 329 330 ret = (d2i_RSAPrivateKey(rsa, &p, len) == NULL) ? 0 : 1; 331 free_AlgorithmIdentifier(&ai); 332 333 CSSM_FreeKey(cspHandle, NULL, &pub_key, CSSM_FALSE); 334 CSSM_FreeKey(cspHandle, NULL, &priv_key, CSSM_FALSE); 335 336 return ret; 337} 338 339static int 340cdsa_rsa_init(RSA *rsa) 341{ 342 return 1; 343} 344 345static int 346cdsa_rsa_finish(RSA *rsa) 347{ 348 return 1; 349} 350 351const RSA_METHOD _hc_rsa_cdsa_method = { 352 "hcrypto cdsa RSA", 353 cdsa_rsa_public_encrypt, 354 cdsa_rsa_public_decrypt, 355 cdsa_rsa_private_encrypt, 356 cdsa_rsa_private_decrypt, 357 NULL, 358 NULL, 359 cdsa_rsa_init, 360 cdsa_rsa_finish, 361 0, 362 NULL, 363 NULL, 364 NULL, 365 cdsa_rsa_generate_key 366}; 367#endif 368 369const RSA_METHOD * 370RSA_cdsa_method(void) 371{ 372#ifdef HAVE_CDSA 373 return &_hc_rsa_cdsa_method; 374#else 375 return NULL; 376#endif 377} 378