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