xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hx509/crypto.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: crypto.c,v 1.1.1.2 2014/04/24 12:45:41 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc  * All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  *
12ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc  *
15ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc  *
19ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc  *    without specific prior written permission.
22ebfedea0SLionel Sambuc  *
23ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34ebfedea0SLionel Sambuc  */
35ebfedea0SLionel Sambuc 
36ebfedea0SLionel Sambuc #include "hx_locl.h"
37ebfedea0SLionel Sambuc 
38ebfedea0SLionel Sambuc struct hx509_crypto;
39ebfedea0SLionel Sambuc 
40ebfedea0SLionel Sambuc struct signature_alg;
41ebfedea0SLionel Sambuc 
42ebfedea0SLionel Sambuc struct hx509_generate_private_context {
43ebfedea0SLionel Sambuc     const heim_oid *key_oid;
44ebfedea0SLionel Sambuc     int isCA;
45ebfedea0SLionel Sambuc     unsigned long num_bits;
46ebfedea0SLionel Sambuc };
47ebfedea0SLionel Sambuc 
48ebfedea0SLionel Sambuc struct hx509_private_key_ops {
49ebfedea0SLionel Sambuc     const char *pemtype;
50ebfedea0SLionel Sambuc     const heim_oid *key_oid;
51ebfedea0SLionel Sambuc     int (*available)(const hx509_private_key,
52ebfedea0SLionel Sambuc 		     const AlgorithmIdentifier *);
53ebfedea0SLionel Sambuc     int (*get_spki)(hx509_context,
54ebfedea0SLionel Sambuc 		    const hx509_private_key,
55ebfedea0SLionel Sambuc 		    SubjectPublicKeyInfo *);
56ebfedea0SLionel Sambuc     int (*export)(hx509_context context,
57ebfedea0SLionel Sambuc 		  const hx509_private_key,
58ebfedea0SLionel Sambuc 		  hx509_key_format_t,
59ebfedea0SLionel Sambuc 		  heim_octet_string *);
60ebfedea0SLionel Sambuc     int (*import)(hx509_context, const AlgorithmIdentifier *,
61ebfedea0SLionel Sambuc 		  const void *, size_t, hx509_key_format_t,
62ebfedea0SLionel Sambuc 		  hx509_private_key);
63ebfedea0SLionel Sambuc     int (*generate_private_key)(hx509_context,
64ebfedea0SLionel Sambuc 				struct hx509_generate_private_context *,
65ebfedea0SLionel Sambuc 				hx509_private_key);
66ebfedea0SLionel Sambuc     BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);
67ebfedea0SLionel Sambuc };
68ebfedea0SLionel Sambuc 
69ebfedea0SLionel Sambuc struct hx509_private_key {
70ebfedea0SLionel Sambuc     unsigned int ref;
71ebfedea0SLionel Sambuc     const struct signature_alg *md;
72ebfedea0SLionel Sambuc     const heim_oid *signature_alg;
73ebfedea0SLionel Sambuc     union {
74ebfedea0SLionel Sambuc 	RSA *rsa;
75ebfedea0SLionel Sambuc 	void *keydata;
76ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
77ebfedea0SLionel Sambuc 	EC_KEY *ecdsa;
78ebfedea0SLionel Sambuc #endif
79ebfedea0SLionel Sambuc     } private_key;
80ebfedea0SLionel Sambuc     hx509_private_key_ops *ops;
81ebfedea0SLionel Sambuc };
82ebfedea0SLionel Sambuc 
83ebfedea0SLionel Sambuc /*
84ebfedea0SLionel Sambuc  *
85ebfedea0SLionel Sambuc  */
86ebfedea0SLionel Sambuc 
87ebfedea0SLionel Sambuc struct signature_alg {
88ebfedea0SLionel Sambuc     const char *name;
89ebfedea0SLionel Sambuc     const heim_oid *sig_oid;
90ebfedea0SLionel Sambuc     const AlgorithmIdentifier *sig_alg;
91ebfedea0SLionel Sambuc     const heim_oid *key_oid;
92ebfedea0SLionel Sambuc     const AlgorithmIdentifier *digest_alg;
93ebfedea0SLionel Sambuc     int flags;
94ebfedea0SLionel Sambuc #define PROVIDE_CONF	0x1
95ebfedea0SLionel Sambuc #define REQUIRE_SIGNER	0x2
96ebfedea0SLionel Sambuc #define SELF_SIGNED_OK	0x4
97ebfedea0SLionel Sambuc 
98ebfedea0SLionel Sambuc #define SIG_DIGEST	0x100
99ebfedea0SLionel Sambuc #define SIG_PUBLIC_SIG	0x200
100ebfedea0SLionel Sambuc #define SIG_SECRET	0x400
101ebfedea0SLionel Sambuc 
102ebfedea0SLionel Sambuc #define RA_RSA_USES_DIGEST_INFO 0x1000000
103ebfedea0SLionel Sambuc 
104ebfedea0SLionel Sambuc     time_t best_before; /* refuse signature made after best before date */
105ebfedea0SLionel Sambuc     const EVP_MD *(*evp_md)(void);
106ebfedea0SLionel Sambuc     int (*verify_signature)(hx509_context context,
107ebfedea0SLionel Sambuc 			    const struct signature_alg *,
108ebfedea0SLionel Sambuc 			    const Certificate *,
109ebfedea0SLionel Sambuc 			    const AlgorithmIdentifier *,
110ebfedea0SLionel Sambuc 			    const heim_octet_string *,
111ebfedea0SLionel Sambuc 			    const heim_octet_string *);
112ebfedea0SLionel Sambuc     int (*create_signature)(hx509_context,
113ebfedea0SLionel Sambuc 			    const struct signature_alg *,
114ebfedea0SLionel Sambuc 			    const hx509_private_key,
115ebfedea0SLionel Sambuc 			    const AlgorithmIdentifier *,
116ebfedea0SLionel Sambuc 			    const heim_octet_string *,
117ebfedea0SLionel Sambuc 			    AlgorithmIdentifier *,
118ebfedea0SLionel Sambuc 			    heim_octet_string *);
119ebfedea0SLionel Sambuc     int digest_size;
120ebfedea0SLionel Sambuc };
121ebfedea0SLionel Sambuc 
122ebfedea0SLionel Sambuc static const struct signature_alg *
123ebfedea0SLionel Sambuc find_sig_alg(const heim_oid *oid);
124ebfedea0SLionel Sambuc 
125ebfedea0SLionel Sambuc /*
126ebfedea0SLionel Sambuc  *
127ebfedea0SLionel Sambuc  */
128ebfedea0SLionel Sambuc 
129ebfedea0SLionel Sambuc static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
130ebfedea0SLionel Sambuc 
131ebfedea0SLionel Sambuc static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
132ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_sha512_data = {
133ebfedea0SLionel Sambuc     { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
134ebfedea0SLionel Sambuc };
135ebfedea0SLionel Sambuc 
136ebfedea0SLionel Sambuc static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
137ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_sha384_data = {
138ebfedea0SLionel Sambuc     { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
139ebfedea0SLionel Sambuc };
140ebfedea0SLionel Sambuc 
141ebfedea0SLionel Sambuc static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
142ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_sha256_data = {
143ebfedea0SLionel Sambuc     { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
144ebfedea0SLionel Sambuc };
145ebfedea0SLionel Sambuc 
146ebfedea0SLionel Sambuc static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
147ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_sha1_data = {
148ebfedea0SLionel Sambuc     { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
149ebfedea0SLionel Sambuc };
150ebfedea0SLionel Sambuc 
151ebfedea0SLionel Sambuc static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
152ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_md5_data = {
153ebfedea0SLionel Sambuc     { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
154ebfedea0SLionel Sambuc };
155ebfedea0SLionel Sambuc 
156ebfedea0SLionel Sambuc static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
157ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
158ebfedea0SLionel Sambuc     { 6, rk_UNCONST(ecPublicKey) }, NULL
159ebfedea0SLionel Sambuc };
160ebfedea0SLionel Sambuc 
161ebfedea0SLionel Sambuc static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
162ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
163ebfedea0SLionel Sambuc     { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
164ebfedea0SLionel Sambuc };
165ebfedea0SLionel Sambuc 
166ebfedea0SLionel Sambuc static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
167ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
168ebfedea0SLionel Sambuc     { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
169ebfedea0SLionel Sambuc };
170ebfedea0SLionel Sambuc 
171ebfedea0SLionel Sambuc static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
172ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
173ebfedea0SLionel Sambuc     { 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL
174ebfedea0SLionel Sambuc };
175ebfedea0SLionel Sambuc 
176ebfedea0SLionel Sambuc static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
177ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
178ebfedea0SLionel Sambuc     { 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL
179ebfedea0SLionel Sambuc };
180ebfedea0SLionel Sambuc 
181ebfedea0SLionel Sambuc static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
182ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
183ebfedea0SLionel Sambuc     { 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL
184ebfedea0SLionel Sambuc };
185ebfedea0SLionel Sambuc 
186ebfedea0SLionel Sambuc static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
187ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
188ebfedea0SLionel Sambuc     { 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL
189ebfedea0SLionel Sambuc };
190ebfedea0SLionel Sambuc 
191ebfedea0SLionel Sambuc static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
192ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
193ebfedea0SLionel Sambuc     { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
194ebfedea0SLionel Sambuc };
195ebfedea0SLionel Sambuc 
196ebfedea0SLionel Sambuc static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
197ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_data = {
198ebfedea0SLionel Sambuc     { 7, rk_UNCONST(rsa_oid) }, NULL
199ebfedea0SLionel Sambuc };
200ebfedea0SLionel Sambuc 
201ebfedea0SLionel Sambuc static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
202ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
203ebfedea0SLionel Sambuc     { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
204ebfedea0SLionel Sambuc };
205ebfedea0SLionel Sambuc 
206ebfedea0SLionel Sambuc static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
207ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
208ebfedea0SLionel Sambuc     { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
209ebfedea0SLionel Sambuc };
210ebfedea0SLionel Sambuc 
211ebfedea0SLionel Sambuc static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
212ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
213ebfedea0SLionel Sambuc     { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
214ebfedea0SLionel Sambuc };
215ebfedea0SLionel Sambuc 
216ebfedea0SLionel Sambuc static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
217ebfedea0SLionel Sambuc const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
218ebfedea0SLionel Sambuc     { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
219ebfedea0SLionel Sambuc };
220ebfedea0SLionel Sambuc 
221ebfedea0SLionel Sambuc /*
222ebfedea0SLionel Sambuc  *
223ebfedea0SLionel Sambuc  */
224ebfedea0SLionel Sambuc 
225ebfedea0SLionel Sambuc static BIGNUM *
heim_int2BN(const heim_integer * i)226ebfedea0SLionel Sambuc heim_int2BN(const heim_integer *i)
227ebfedea0SLionel Sambuc {
228ebfedea0SLionel Sambuc     BIGNUM *bn;
229ebfedea0SLionel Sambuc 
230ebfedea0SLionel Sambuc     bn = BN_bin2bn(i->data, i->length, NULL);
231ebfedea0SLionel Sambuc     BN_set_negative(bn, i->negative);
232ebfedea0SLionel Sambuc     return bn;
233ebfedea0SLionel Sambuc }
234ebfedea0SLionel Sambuc 
235ebfedea0SLionel Sambuc /*
236ebfedea0SLionel Sambuc  *
237ebfedea0SLionel Sambuc  */
238ebfedea0SLionel Sambuc 
239ebfedea0SLionel Sambuc static int
set_digest_alg(DigestAlgorithmIdentifier * id,const heim_oid * oid,const void * param,size_t length)240ebfedea0SLionel Sambuc set_digest_alg(DigestAlgorithmIdentifier *id,
241ebfedea0SLionel Sambuc 	       const heim_oid *oid,
242ebfedea0SLionel Sambuc 	       const void *param, size_t length)
243ebfedea0SLionel Sambuc {
244ebfedea0SLionel Sambuc     int ret;
245ebfedea0SLionel Sambuc     if (param) {
246ebfedea0SLionel Sambuc 	id->parameters = malloc(sizeof(*id->parameters));
247ebfedea0SLionel Sambuc 	if (id->parameters == NULL)
248ebfedea0SLionel Sambuc 	    return ENOMEM;
249ebfedea0SLionel Sambuc 	id->parameters->data = malloc(length);
250ebfedea0SLionel Sambuc 	if (id->parameters->data == NULL) {
251ebfedea0SLionel Sambuc 	    free(id->parameters);
252ebfedea0SLionel Sambuc 	    id->parameters = NULL;
253ebfedea0SLionel Sambuc 	    return ENOMEM;
254ebfedea0SLionel Sambuc 	}
255ebfedea0SLionel Sambuc 	memcpy(id->parameters->data, param, length);
256ebfedea0SLionel Sambuc 	id->parameters->length = length;
257ebfedea0SLionel Sambuc     } else
258ebfedea0SLionel Sambuc 	id->parameters = NULL;
259ebfedea0SLionel Sambuc     ret = der_copy_oid(oid, &id->algorithm);
260ebfedea0SLionel Sambuc     if (ret) {
261ebfedea0SLionel Sambuc 	if (id->parameters) {
262ebfedea0SLionel Sambuc 	    free(id->parameters->data);
263ebfedea0SLionel Sambuc 	    free(id->parameters);
264ebfedea0SLionel Sambuc 	    id->parameters = NULL;
265ebfedea0SLionel Sambuc 	}
266ebfedea0SLionel Sambuc 	return ret;
267ebfedea0SLionel Sambuc     }
268ebfedea0SLionel Sambuc     return 0;
269ebfedea0SLionel Sambuc }
270ebfedea0SLionel Sambuc 
271ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
272ebfedea0SLionel Sambuc 
273ebfedea0SLionel Sambuc static int
heim_oid2ecnid(heim_oid * oid)274ebfedea0SLionel Sambuc heim_oid2ecnid(heim_oid *oid)
275ebfedea0SLionel Sambuc {
276ebfedea0SLionel Sambuc     /*
277ebfedea0SLionel Sambuc      * Now map to openssl OID fun
278ebfedea0SLionel Sambuc      */
279ebfedea0SLionel Sambuc 
280ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
281ebfedea0SLionel Sambuc 	return NID_X9_62_prime256v1;
282ebfedea0SLionel Sambuc     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
283ebfedea0SLionel Sambuc 	return NID_secp160r1;
284ebfedea0SLionel Sambuc     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
285ebfedea0SLionel Sambuc 	return NID_secp160r2;
286ebfedea0SLionel Sambuc 
287ebfedea0SLionel Sambuc     return -1;
288ebfedea0SLionel Sambuc }
289ebfedea0SLionel Sambuc 
290ebfedea0SLionel Sambuc static int
parse_ECParameters(hx509_context context,heim_octet_string * parameters,int * nid)291ebfedea0SLionel Sambuc parse_ECParameters(hx509_context context,
292ebfedea0SLionel Sambuc 		   heim_octet_string *parameters, int *nid)
293ebfedea0SLionel Sambuc {
294ebfedea0SLionel Sambuc     ECParameters ecparam;
295ebfedea0SLionel Sambuc     size_t size;
296ebfedea0SLionel Sambuc     int ret;
297ebfedea0SLionel Sambuc 
298ebfedea0SLionel Sambuc     if (parameters == NULL) {
299ebfedea0SLionel Sambuc 	ret = HX509_PARSING_KEY_FAILED;
300ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
301ebfedea0SLionel Sambuc 			       "EC parameters missing");
302ebfedea0SLionel Sambuc 	return ret;
303ebfedea0SLionel Sambuc     }
304ebfedea0SLionel Sambuc 
305ebfedea0SLionel Sambuc     ret = decode_ECParameters(parameters->data, parameters->length,
306ebfedea0SLionel Sambuc 			      &ecparam, &size);
307ebfedea0SLionel Sambuc     if (ret) {
308ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
309ebfedea0SLionel Sambuc 			       "Failed to decode EC parameters");
310ebfedea0SLionel Sambuc 	return ret;
311ebfedea0SLionel Sambuc     }
312ebfedea0SLionel Sambuc 
313ebfedea0SLionel Sambuc     if (ecparam.element != choice_ECParameters_namedCurve) {
314ebfedea0SLionel Sambuc 	free_ECParameters(&ecparam);
315ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
316ebfedea0SLionel Sambuc 			       "EC parameters is not a named curve");
317ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
318ebfedea0SLionel Sambuc     }
319ebfedea0SLionel Sambuc 
320ebfedea0SLionel Sambuc     *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
321ebfedea0SLionel Sambuc     free_ECParameters(&ecparam);
322ebfedea0SLionel Sambuc     if (*nid == -1) {
323ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
324ebfedea0SLionel Sambuc 			       "Failed to find matcing NID for EC curve");
325ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
326ebfedea0SLionel Sambuc     }
327ebfedea0SLionel Sambuc     return 0;
328ebfedea0SLionel Sambuc }
329ebfedea0SLionel Sambuc 
330ebfedea0SLionel Sambuc 
331ebfedea0SLionel Sambuc /*
332ebfedea0SLionel Sambuc  *
333ebfedea0SLionel Sambuc  */
334ebfedea0SLionel Sambuc 
335ebfedea0SLionel Sambuc static int
ecdsa_verify_signature(hx509_context context,const struct signature_alg * sig_alg,const Certificate * signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)336ebfedea0SLionel Sambuc ecdsa_verify_signature(hx509_context context,
337ebfedea0SLionel Sambuc 		       const struct signature_alg *sig_alg,
338ebfedea0SLionel Sambuc 		       const Certificate *signer,
339ebfedea0SLionel Sambuc 		       const AlgorithmIdentifier *alg,
340ebfedea0SLionel Sambuc 		       const heim_octet_string *data,
341ebfedea0SLionel Sambuc 		       const heim_octet_string *sig)
342ebfedea0SLionel Sambuc {
343ebfedea0SLionel Sambuc     const AlgorithmIdentifier *digest_alg;
344ebfedea0SLionel Sambuc     const SubjectPublicKeyInfo *spi;
345ebfedea0SLionel Sambuc     heim_octet_string digest;
346ebfedea0SLionel Sambuc     int ret;
347ebfedea0SLionel Sambuc     EC_KEY *key = NULL;
348ebfedea0SLionel Sambuc     int groupnid;
349ebfedea0SLionel Sambuc     EC_GROUP *group;
350ebfedea0SLionel Sambuc     const unsigned char *p;
351ebfedea0SLionel Sambuc     long len;
352ebfedea0SLionel Sambuc 
353ebfedea0SLionel Sambuc     digest_alg = sig_alg->digest_alg;
354ebfedea0SLionel Sambuc 
355ebfedea0SLionel Sambuc     ret = _hx509_create_signature(context,
356ebfedea0SLionel Sambuc 				  NULL,
357ebfedea0SLionel Sambuc 				  digest_alg,
358ebfedea0SLionel Sambuc 				  data,
359ebfedea0SLionel Sambuc 				  NULL,
360ebfedea0SLionel Sambuc 				  &digest);
361ebfedea0SLionel Sambuc     if (ret)
362ebfedea0SLionel Sambuc 	return ret;
363ebfedea0SLionel Sambuc 
364ebfedea0SLionel Sambuc     /* set up EC KEY */
365ebfedea0SLionel Sambuc     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
366ebfedea0SLionel Sambuc 
367ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
368ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
369ebfedea0SLionel Sambuc 
370ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
371ebfedea0SLionel Sambuc     /*
372ebfedea0SLionel Sambuc      * Find the group id
373ebfedea0SLionel Sambuc      */
374ebfedea0SLionel Sambuc 
375ebfedea0SLionel Sambuc     ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
376ebfedea0SLionel Sambuc     if (ret) {
377ebfedea0SLionel Sambuc 	der_free_octet_string(&digest);
378ebfedea0SLionel Sambuc 	return ret;
379ebfedea0SLionel Sambuc     }
380ebfedea0SLionel Sambuc 
381ebfedea0SLionel Sambuc     /*
382ebfedea0SLionel Sambuc      * Create group, key, parse key
383ebfedea0SLionel Sambuc      */
384ebfedea0SLionel Sambuc 
385ebfedea0SLionel Sambuc     key = EC_KEY_new();
386ebfedea0SLionel Sambuc     group = EC_GROUP_new_by_curve_name(groupnid);
387ebfedea0SLionel Sambuc     EC_KEY_set_group(key, group);
388ebfedea0SLionel Sambuc     EC_GROUP_free(group);
389ebfedea0SLionel Sambuc 
390ebfedea0SLionel Sambuc     p = spi->subjectPublicKey.data;
391ebfedea0SLionel Sambuc     len = spi->subjectPublicKey.length / 8;
392ebfedea0SLionel Sambuc 
393ebfedea0SLionel Sambuc     if (o2i_ECPublicKey(&key, &p, len) == NULL) {
394ebfedea0SLionel Sambuc 	EC_KEY_free(key);
395ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
396ebfedea0SLionel Sambuc     }
397ebfedea0SLionel Sambuc #else
398ebfedea0SLionel Sambuc     key = SubjectPublicKeyInfo2EC_KEY(spi);
399ebfedea0SLionel Sambuc #endif
400ebfedea0SLionel Sambuc 
401ebfedea0SLionel Sambuc     ret = ECDSA_verify(-1, digest.data, digest.length,
402ebfedea0SLionel Sambuc 		       sig->data, sig->length, key);
403ebfedea0SLionel Sambuc     der_free_octet_string(&digest);
404ebfedea0SLionel Sambuc     EC_KEY_free(key);
405ebfedea0SLionel Sambuc     if (ret != 1) {
406ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
407ebfedea0SLionel Sambuc 	return ret;
408ebfedea0SLionel Sambuc     }
409ebfedea0SLionel Sambuc 
410ebfedea0SLionel Sambuc     return 0;
411ebfedea0SLionel Sambuc }
412ebfedea0SLionel Sambuc 
413ebfedea0SLionel Sambuc static int
ecdsa_create_signature(hx509_context context,const struct signature_alg * sig_alg,const hx509_private_key signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,AlgorithmIdentifier * signatureAlgorithm,heim_octet_string * sig)414ebfedea0SLionel Sambuc ecdsa_create_signature(hx509_context context,
415ebfedea0SLionel Sambuc 		       const struct signature_alg *sig_alg,
416ebfedea0SLionel Sambuc 		       const hx509_private_key signer,
417ebfedea0SLionel Sambuc 		       const AlgorithmIdentifier *alg,
418ebfedea0SLionel Sambuc 		       const heim_octet_string *data,
419ebfedea0SLionel Sambuc 		       AlgorithmIdentifier *signatureAlgorithm,
420ebfedea0SLionel Sambuc 		       heim_octet_string *sig)
421ebfedea0SLionel Sambuc {
422ebfedea0SLionel Sambuc     const AlgorithmIdentifier *digest_alg;
423ebfedea0SLionel Sambuc     heim_octet_string indata;
424ebfedea0SLionel Sambuc     const heim_oid *sig_oid;
425ebfedea0SLionel Sambuc     unsigned int siglen;
426ebfedea0SLionel Sambuc     int ret;
427ebfedea0SLionel Sambuc 
428ebfedea0SLionel Sambuc     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
429ebfedea0SLionel Sambuc 	_hx509_abort("internal error passing private key to wrong ops");
430ebfedea0SLionel Sambuc 
431ebfedea0SLionel Sambuc     sig_oid = sig_alg->sig_oid;
432ebfedea0SLionel Sambuc     digest_alg = sig_alg->digest_alg;
433ebfedea0SLionel Sambuc 
434ebfedea0SLionel Sambuc     if (signatureAlgorithm) {
435ebfedea0SLionel Sambuc 	ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
436ebfedea0SLionel Sambuc 	if (ret) {
437ebfedea0SLionel Sambuc 	    hx509_clear_error_string(context);
438ebfedea0SLionel Sambuc 	    goto error;
439ebfedea0SLionel Sambuc 	}
440ebfedea0SLionel Sambuc     }
441ebfedea0SLionel Sambuc 
442ebfedea0SLionel Sambuc     ret = _hx509_create_signature(context,
443ebfedea0SLionel Sambuc 				  NULL,
444ebfedea0SLionel Sambuc 				  digest_alg,
445ebfedea0SLionel Sambuc 				  data,
446ebfedea0SLionel Sambuc 				  NULL,
447ebfedea0SLionel Sambuc 				  &indata);
448ebfedea0SLionel Sambuc     if (ret) {
449ebfedea0SLionel Sambuc 	if (signatureAlgorithm)
450ebfedea0SLionel Sambuc 	    free_AlgorithmIdentifier(signatureAlgorithm);
451ebfedea0SLionel Sambuc 	goto error;
452ebfedea0SLionel Sambuc     }
453ebfedea0SLionel Sambuc 
454ebfedea0SLionel Sambuc     sig->length = ECDSA_size(signer->private_key.ecdsa);
455ebfedea0SLionel Sambuc     sig->data = malloc(sig->length);
456ebfedea0SLionel Sambuc     if (sig->data == NULL) {
457ebfedea0SLionel Sambuc 	der_free_octet_string(&indata);
458ebfedea0SLionel Sambuc 	ret = ENOMEM;
459ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
460ebfedea0SLionel Sambuc 	goto error;
461ebfedea0SLionel Sambuc     }
462ebfedea0SLionel Sambuc 
463ebfedea0SLionel Sambuc     siglen = sig->length;
464ebfedea0SLionel Sambuc 
465ebfedea0SLionel Sambuc     ret = ECDSA_sign(-1, indata.data, indata.length,
466ebfedea0SLionel Sambuc 		     sig->data, &siglen, signer->private_key.ecdsa);
467ebfedea0SLionel Sambuc     der_free_octet_string(&indata);
468ebfedea0SLionel Sambuc     if (ret != 1) {
469ebfedea0SLionel Sambuc 	ret = HX509_CMS_FAILED_CREATE_SIGATURE;
470ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
471ebfedea0SLionel Sambuc 			       "ECDSA sign failed: %d", ret);
472ebfedea0SLionel Sambuc 	goto error;
473ebfedea0SLionel Sambuc     }
474ebfedea0SLionel Sambuc     if (siglen > sig->length)
475ebfedea0SLionel Sambuc 	_hx509_abort("ECDSA signature prelen longer the output len");
476ebfedea0SLionel Sambuc 
477ebfedea0SLionel Sambuc     sig->length = siglen;
478ebfedea0SLionel Sambuc 
479ebfedea0SLionel Sambuc     return 0;
480ebfedea0SLionel Sambuc  error:
481ebfedea0SLionel Sambuc     if (signatureAlgorithm)
482ebfedea0SLionel Sambuc 	free_AlgorithmIdentifier(signatureAlgorithm);
483ebfedea0SLionel Sambuc     return ret;
484ebfedea0SLionel Sambuc }
485ebfedea0SLionel Sambuc 
486ebfedea0SLionel Sambuc static int
ecdsa_available(const hx509_private_key signer,const AlgorithmIdentifier * sig_alg)487ebfedea0SLionel Sambuc ecdsa_available(const hx509_private_key signer,
488ebfedea0SLionel Sambuc 		const AlgorithmIdentifier *sig_alg)
489ebfedea0SLionel Sambuc {
490ebfedea0SLionel Sambuc     const struct signature_alg *sig;
491ebfedea0SLionel Sambuc     const EC_GROUP *group;
492ebfedea0SLionel Sambuc     BN_CTX *bnctx = NULL;
493ebfedea0SLionel Sambuc     BIGNUM *order = NULL;
494ebfedea0SLionel Sambuc     int ret = 0;
495ebfedea0SLionel Sambuc 
496ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
497ebfedea0SLionel Sambuc 	_hx509_abort("internal error passing private key to wrong ops");
498ebfedea0SLionel Sambuc 
499ebfedea0SLionel Sambuc     sig = find_sig_alg(&sig_alg->algorithm);
500ebfedea0SLionel Sambuc 
501ebfedea0SLionel Sambuc     if (sig == NULL || sig->digest_size == 0)
502ebfedea0SLionel Sambuc 	return 0;
503ebfedea0SLionel Sambuc 
504ebfedea0SLionel Sambuc     group = EC_KEY_get0_group(signer->private_key.ecdsa);
505ebfedea0SLionel Sambuc     if (group == NULL)
506ebfedea0SLionel Sambuc 	return 0;
507ebfedea0SLionel Sambuc 
508ebfedea0SLionel Sambuc     bnctx = BN_CTX_new();
509ebfedea0SLionel Sambuc     order = BN_new();
510ebfedea0SLionel Sambuc     if (order == NULL)
511ebfedea0SLionel Sambuc 	goto err;
512ebfedea0SLionel Sambuc 
513ebfedea0SLionel Sambuc     if (EC_GROUP_get_order(group, order, bnctx) != 1)
514ebfedea0SLionel Sambuc 	goto err;
515ebfedea0SLionel Sambuc 
516ebfedea0SLionel Sambuc     if (BN_num_bytes(order) > sig->digest_size)
517ebfedea0SLionel Sambuc 	ret = 1;
518ebfedea0SLionel Sambuc  err:
519ebfedea0SLionel Sambuc     if (bnctx)
520ebfedea0SLionel Sambuc 	BN_CTX_free(bnctx);
521ebfedea0SLionel Sambuc     if (order)
522ebfedea0SLionel Sambuc 	BN_clear_free(order);
523ebfedea0SLionel Sambuc 
524ebfedea0SLionel Sambuc     return ret;
525ebfedea0SLionel Sambuc }
526ebfedea0SLionel Sambuc 
527ebfedea0SLionel Sambuc 
528ebfedea0SLionel Sambuc #endif /* HAVE_OPENSSL */
529ebfedea0SLionel Sambuc 
530ebfedea0SLionel Sambuc /*
531ebfedea0SLionel Sambuc  *
532ebfedea0SLionel Sambuc  */
533ebfedea0SLionel Sambuc 
534ebfedea0SLionel Sambuc static int
rsa_verify_signature(hx509_context context,const struct signature_alg * sig_alg,const Certificate * signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)535ebfedea0SLionel Sambuc rsa_verify_signature(hx509_context context,
536ebfedea0SLionel Sambuc 		     const struct signature_alg *sig_alg,
537ebfedea0SLionel Sambuc 		     const Certificate *signer,
538ebfedea0SLionel Sambuc 		     const AlgorithmIdentifier *alg,
539ebfedea0SLionel Sambuc 		     const heim_octet_string *data,
540ebfedea0SLionel Sambuc 		     const heim_octet_string *sig)
541ebfedea0SLionel Sambuc {
542ebfedea0SLionel Sambuc     const SubjectPublicKeyInfo *spi;
543ebfedea0SLionel Sambuc     DigestInfo di;
544ebfedea0SLionel Sambuc     unsigned char *to;
545ebfedea0SLionel Sambuc     int tosize, retsize;
546ebfedea0SLionel Sambuc     int ret;
547ebfedea0SLionel Sambuc     RSA *rsa;
548ebfedea0SLionel Sambuc     size_t size;
549ebfedea0SLionel Sambuc     const unsigned char *p;
550ebfedea0SLionel Sambuc 
551ebfedea0SLionel Sambuc     memset(&di, 0, sizeof(di));
552ebfedea0SLionel Sambuc 
553ebfedea0SLionel Sambuc     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
554ebfedea0SLionel Sambuc 
555ebfedea0SLionel Sambuc     p = spi->subjectPublicKey.data;
556ebfedea0SLionel Sambuc     size = spi->subjectPublicKey.length / 8;
557ebfedea0SLionel Sambuc 
558ebfedea0SLionel Sambuc     rsa = d2i_RSAPublicKey(NULL, &p, size);
559ebfedea0SLionel Sambuc     if (rsa == NULL) {
560ebfedea0SLionel Sambuc 	ret = ENOMEM;
561ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
562ebfedea0SLionel Sambuc 	goto out;
563ebfedea0SLionel Sambuc     }
564ebfedea0SLionel Sambuc 
565ebfedea0SLionel Sambuc     tosize = RSA_size(rsa);
566ebfedea0SLionel Sambuc     to = malloc(tosize);
567ebfedea0SLionel Sambuc     if (to == NULL) {
568ebfedea0SLionel Sambuc 	ret = ENOMEM;
569ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
570ebfedea0SLionel Sambuc 	goto out;
571ebfedea0SLionel Sambuc     }
572ebfedea0SLionel Sambuc 
573ebfedea0SLionel Sambuc     retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data,
574ebfedea0SLionel Sambuc 				 to, rsa, RSA_PKCS1_PADDING);
575ebfedea0SLionel Sambuc     if (retsize <= 0) {
576ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
577ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
578ebfedea0SLionel Sambuc 			       "RSA public decrypt failed: %d", retsize);
579ebfedea0SLionel Sambuc 	free(to);
580ebfedea0SLionel Sambuc 	goto out;
581ebfedea0SLionel Sambuc     }
582ebfedea0SLionel Sambuc     if (retsize > tosize)
583ebfedea0SLionel Sambuc 	_hx509_abort("internal rsa decryption failure: ret > tosize");
584ebfedea0SLionel Sambuc 
585ebfedea0SLionel Sambuc     if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) {
586ebfedea0SLionel Sambuc 
587ebfedea0SLionel Sambuc 	ret = decode_DigestInfo(to, retsize, &di, &size);
588ebfedea0SLionel Sambuc 	free(to);
589ebfedea0SLionel Sambuc 	if (ret) {
590ebfedea0SLionel Sambuc 	    goto out;
591ebfedea0SLionel Sambuc 	}
592ebfedea0SLionel Sambuc 
593ebfedea0SLionel Sambuc 	/* Check for extra data inside the sigature */
594*0a6a1f1dSLionel Sambuc 	if (size != (size_t)retsize) {
595ebfedea0SLionel Sambuc 	    ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
596ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret, "size from decryption mismatch");
597ebfedea0SLionel Sambuc 	    goto out;
598ebfedea0SLionel Sambuc 	}
599ebfedea0SLionel Sambuc 
600ebfedea0SLionel Sambuc 	if (sig_alg->digest_alg &&
601ebfedea0SLionel Sambuc 	    der_heim_oid_cmp(&di.digestAlgorithm.algorithm,
602ebfedea0SLionel Sambuc 			     &sig_alg->digest_alg->algorithm) != 0)
603ebfedea0SLionel Sambuc 	{
604ebfedea0SLionel Sambuc 	    ret = HX509_CRYPTO_OID_MISMATCH;
605ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch");
606ebfedea0SLionel Sambuc 	    goto out;
607ebfedea0SLionel Sambuc 	}
608ebfedea0SLionel Sambuc 
609ebfedea0SLionel Sambuc 	/* verify that the parameters are NULL or the NULL-type */
610ebfedea0SLionel Sambuc 	if (di.digestAlgorithm.parameters != NULL &&
611ebfedea0SLionel Sambuc 	    (di.digestAlgorithm.parameters->length != 2 ||
612ebfedea0SLionel Sambuc 	     memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0))
613ebfedea0SLionel Sambuc 	{
614ebfedea0SLionel Sambuc 	    ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
615ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature");
616ebfedea0SLionel Sambuc 	    goto out;
617ebfedea0SLionel Sambuc 	}
618ebfedea0SLionel Sambuc 
619ebfedea0SLionel Sambuc 	ret = _hx509_verify_signature(context,
620ebfedea0SLionel Sambuc 				      NULL,
621ebfedea0SLionel Sambuc 				      &di.digestAlgorithm,
622ebfedea0SLionel Sambuc 				      data,
623ebfedea0SLionel Sambuc 				      &di.digest);
624ebfedea0SLionel Sambuc     } else {
625*0a6a1f1dSLionel Sambuc 	if ((size_t)retsize != data->length ||
626ebfedea0SLionel Sambuc 	    ct_memcmp(to, data->data, retsize) != 0)
627ebfedea0SLionel Sambuc 	{
628ebfedea0SLionel Sambuc 	    ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
629ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret, "RSA Signature incorrect");
630ebfedea0SLionel Sambuc 	    goto out;
631ebfedea0SLionel Sambuc 	}
632ebfedea0SLionel Sambuc 	free(to);
633ebfedea0SLionel Sambuc     }
634ebfedea0SLionel Sambuc     ret = 0;
635ebfedea0SLionel Sambuc 
636ebfedea0SLionel Sambuc  out:
637ebfedea0SLionel Sambuc     free_DigestInfo(&di);
638ebfedea0SLionel Sambuc     if (rsa)
639ebfedea0SLionel Sambuc 	RSA_free(rsa);
640ebfedea0SLionel Sambuc     return ret;
641ebfedea0SLionel Sambuc }
642ebfedea0SLionel Sambuc 
643ebfedea0SLionel Sambuc static int
rsa_create_signature(hx509_context context,const struct signature_alg * sig_alg,const hx509_private_key signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,AlgorithmIdentifier * signatureAlgorithm,heim_octet_string * sig)644ebfedea0SLionel Sambuc rsa_create_signature(hx509_context context,
645ebfedea0SLionel Sambuc 		     const struct signature_alg *sig_alg,
646ebfedea0SLionel Sambuc 		     const hx509_private_key signer,
647ebfedea0SLionel Sambuc 		     const AlgorithmIdentifier *alg,
648ebfedea0SLionel Sambuc 		     const heim_octet_string *data,
649ebfedea0SLionel Sambuc 		     AlgorithmIdentifier *signatureAlgorithm,
650ebfedea0SLionel Sambuc 		     heim_octet_string *sig)
651ebfedea0SLionel Sambuc {
652ebfedea0SLionel Sambuc     const AlgorithmIdentifier *digest_alg;
653ebfedea0SLionel Sambuc     heim_octet_string indata;
654ebfedea0SLionel Sambuc     const heim_oid *sig_oid;
655ebfedea0SLionel Sambuc     size_t size;
656ebfedea0SLionel Sambuc     int ret;
657ebfedea0SLionel Sambuc 
658ebfedea0SLionel Sambuc     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0)
659ebfedea0SLionel Sambuc 	return HX509_ALG_NOT_SUPP;
660ebfedea0SLionel Sambuc 
661ebfedea0SLionel Sambuc     if (alg)
662ebfedea0SLionel Sambuc 	sig_oid = &alg->algorithm;
663ebfedea0SLionel Sambuc     else
664ebfedea0SLionel Sambuc 	sig_oid = signer->signature_alg;
665ebfedea0SLionel Sambuc 
666ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) {
667ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_sha512();
668ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) {
669ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_sha384();
670ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) {
671ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_sha256();
672ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) {
673ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_sha1();
674ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
675ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_md5();
676ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
677ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_md5();
678ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) {
679ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_sha1();
680ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
681ebfedea0SLionel Sambuc 	digest_alg = hx509_signature_sha1();
682ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) {
683ebfedea0SLionel Sambuc 	digest_alg = NULL;
684ebfedea0SLionel Sambuc     } else
685ebfedea0SLionel Sambuc 	return HX509_ALG_NOT_SUPP;
686ebfedea0SLionel Sambuc 
687ebfedea0SLionel Sambuc     if (signatureAlgorithm) {
688ebfedea0SLionel Sambuc 	ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
689ebfedea0SLionel Sambuc 	if (ret) {
690ebfedea0SLionel Sambuc 	    hx509_clear_error_string(context);
691ebfedea0SLionel Sambuc 	    return ret;
692ebfedea0SLionel Sambuc 	}
693ebfedea0SLionel Sambuc     }
694ebfedea0SLionel Sambuc 
695ebfedea0SLionel Sambuc     if (digest_alg) {
696ebfedea0SLionel Sambuc 	DigestInfo di;
697ebfedea0SLionel Sambuc 	memset(&di, 0, sizeof(di));
698ebfedea0SLionel Sambuc 
699ebfedea0SLionel Sambuc 	ret = _hx509_create_signature(context,
700ebfedea0SLionel Sambuc 				      NULL,
701ebfedea0SLionel Sambuc 				      digest_alg,
702ebfedea0SLionel Sambuc 				      data,
703ebfedea0SLionel Sambuc 				      &di.digestAlgorithm,
704ebfedea0SLionel Sambuc 				      &di.digest);
705ebfedea0SLionel Sambuc 	if (ret)
706ebfedea0SLionel Sambuc 	    return ret;
707ebfedea0SLionel Sambuc 	ASN1_MALLOC_ENCODE(DigestInfo,
708ebfedea0SLionel Sambuc 			   indata.data,
709ebfedea0SLionel Sambuc 			   indata.length,
710ebfedea0SLionel Sambuc 			   &di,
711ebfedea0SLionel Sambuc 			   &size,
712ebfedea0SLionel Sambuc 			   ret);
713ebfedea0SLionel Sambuc 	free_DigestInfo(&di);
714ebfedea0SLionel Sambuc 	if (ret) {
715ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret, "out of memory");
716ebfedea0SLionel Sambuc 	    return ret;
717ebfedea0SLionel Sambuc 	}
718ebfedea0SLionel Sambuc 	if (indata.length != size)
719ebfedea0SLionel Sambuc 	    _hx509_abort("internal ASN.1 encoder error");
720ebfedea0SLionel Sambuc     } else {
721ebfedea0SLionel Sambuc 	indata = *data;
722ebfedea0SLionel Sambuc     }
723ebfedea0SLionel Sambuc 
724ebfedea0SLionel Sambuc     sig->length = RSA_size(signer->private_key.rsa);
725ebfedea0SLionel Sambuc     sig->data = malloc(sig->length);
726ebfedea0SLionel Sambuc     if (sig->data == NULL) {
727ebfedea0SLionel Sambuc 	der_free_octet_string(&indata);
728ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
729ebfedea0SLionel Sambuc 	return ENOMEM;
730ebfedea0SLionel Sambuc     }
731ebfedea0SLionel Sambuc 
732ebfedea0SLionel Sambuc     ret = RSA_private_encrypt(indata.length, indata.data,
733ebfedea0SLionel Sambuc 			      sig->data,
734ebfedea0SLionel Sambuc 			      signer->private_key.rsa,
735ebfedea0SLionel Sambuc 			      RSA_PKCS1_PADDING);
736ebfedea0SLionel Sambuc     if (indata.data != data->data)
737ebfedea0SLionel Sambuc 	der_free_octet_string(&indata);
738ebfedea0SLionel Sambuc     if (ret <= 0) {
739ebfedea0SLionel Sambuc 	ret = HX509_CMS_FAILED_CREATE_SIGATURE;
740ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret,
741ebfedea0SLionel Sambuc 			       "RSA private encrypt failed: %d", ret);
742ebfedea0SLionel Sambuc 	return ret;
743ebfedea0SLionel Sambuc     }
744*0a6a1f1dSLionel Sambuc     if ((size_t)ret > sig->length)
745ebfedea0SLionel Sambuc 	_hx509_abort("RSA signature prelen longer the output len");
746ebfedea0SLionel Sambuc 
747ebfedea0SLionel Sambuc     sig->length = ret;
748ebfedea0SLionel Sambuc 
749ebfedea0SLionel Sambuc     return 0;
750ebfedea0SLionel Sambuc }
751ebfedea0SLionel Sambuc 
752ebfedea0SLionel Sambuc static int
rsa_private_key_import(hx509_context context,const AlgorithmIdentifier * keyai,const void * data,size_t len,hx509_key_format_t format,hx509_private_key private_key)753ebfedea0SLionel Sambuc rsa_private_key_import(hx509_context context,
754ebfedea0SLionel Sambuc 		       const AlgorithmIdentifier *keyai,
755ebfedea0SLionel Sambuc 		       const void *data,
756ebfedea0SLionel Sambuc 		       size_t len,
757ebfedea0SLionel Sambuc 		       hx509_key_format_t format,
758ebfedea0SLionel Sambuc 		       hx509_private_key private_key)
759ebfedea0SLionel Sambuc {
760ebfedea0SLionel Sambuc     switch (format) {
761ebfedea0SLionel Sambuc     case HX509_KEY_FORMAT_DER: {
762ebfedea0SLionel Sambuc 	const unsigned char *p = data;
763ebfedea0SLionel Sambuc 
764ebfedea0SLionel Sambuc 	private_key->private_key.rsa =
765ebfedea0SLionel Sambuc 	    d2i_RSAPrivateKey(NULL, &p, len);
766ebfedea0SLionel Sambuc 	if (private_key->private_key.rsa == NULL) {
767ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
768ebfedea0SLionel Sambuc 				   "Failed to parse RSA key");
769ebfedea0SLionel Sambuc 	    return HX509_PARSING_KEY_FAILED;
770ebfedea0SLionel Sambuc 	}
771ebfedea0SLionel Sambuc 	private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
772ebfedea0SLionel Sambuc 	break;
773ebfedea0SLionel Sambuc 
774ebfedea0SLionel Sambuc     }
775ebfedea0SLionel Sambuc     default:
776ebfedea0SLionel Sambuc 	return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
777ebfedea0SLionel Sambuc     }
778ebfedea0SLionel Sambuc 
779ebfedea0SLionel Sambuc     return 0;
780ebfedea0SLionel Sambuc }
781ebfedea0SLionel Sambuc 
782ebfedea0SLionel Sambuc static int
rsa_private_key2SPKI(hx509_context context,hx509_private_key private_key,SubjectPublicKeyInfo * spki)783ebfedea0SLionel Sambuc rsa_private_key2SPKI(hx509_context context,
784ebfedea0SLionel Sambuc 		     hx509_private_key private_key,
785ebfedea0SLionel Sambuc 		     SubjectPublicKeyInfo *spki)
786ebfedea0SLionel Sambuc {
787ebfedea0SLionel Sambuc     int len, ret;
788ebfedea0SLionel Sambuc 
789ebfedea0SLionel Sambuc     memset(spki, 0, sizeof(*spki));
790ebfedea0SLionel Sambuc 
791ebfedea0SLionel Sambuc     len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
792ebfedea0SLionel Sambuc 
793ebfedea0SLionel Sambuc     spki->subjectPublicKey.data = malloc(len);
794ebfedea0SLionel Sambuc     if (spki->subjectPublicKey.data == NULL) {
795ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
796ebfedea0SLionel Sambuc 	return ENOMEM;
797ebfedea0SLionel Sambuc     }
798ebfedea0SLionel Sambuc     spki->subjectPublicKey.length = len * 8;
799ebfedea0SLionel Sambuc 
800ebfedea0SLionel Sambuc     ret = set_digest_alg(&spki->algorithm, ASN1_OID_ID_PKCS1_RSAENCRYPTION,
801ebfedea0SLionel Sambuc 			 "\x05\x00", 2);
802ebfedea0SLionel Sambuc     if (ret) {
803ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "malloc - out of memory");
804ebfedea0SLionel Sambuc 	free(spki->subjectPublicKey.data);
805ebfedea0SLionel Sambuc 	spki->subjectPublicKey.data = NULL;
806ebfedea0SLionel Sambuc 	spki->subjectPublicKey.length = 0;
807ebfedea0SLionel Sambuc 	return ret;
808ebfedea0SLionel Sambuc     }
809ebfedea0SLionel Sambuc 
810ebfedea0SLionel Sambuc     {
811ebfedea0SLionel Sambuc 	unsigned char *pp = spki->subjectPublicKey.data;
812ebfedea0SLionel Sambuc 	i2d_RSAPublicKey(private_key->private_key.rsa, &pp);
813ebfedea0SLionel Sambuc     }
814ebfedea0SLionel Sambuc 
815ebfedea0SLionel Sambuc     return 0;
816ebfedea0SLionel Sambuc }
817ebfedea0SLionel Sambuc 
818ebfedea0SLionel Sambuc static int
rsa_generate_private_key(hx509_context context,struct hx509_generate_private_context * ctx,hx509_private_key private_key)819ebfedea0SLionel Sambuc rsa_generate_private_key(hx509_context context,
820ebfedea0SLionel Sambuc 			 struct hx509_generate_private_context *ctx,
821ebfedea0SLionel Sambuc 			 hx509_private_key private_key)
822ebfedea0SLionel Sambuc {
823ebfedea0SLionel Sambuc     BIGNUM *e;
824ebfedea0SLionel Sambuc     int ret;
825ebfedea0SLionel Sambuc     unsigned long bits;
826ebfedea0SLionel Sambuc 
827ebfedea0SLionel Sambuc     static const int default_rsa_e = 65537;
828ebfedea0SLionel Sambuc     static const int default_rsa_bits = 2048;
829ebfedea0SLionel Sambuc 
830ebfedea0SLionel Sambuc     private_key->private_key.rsa = RSA_new();
831ebfedea0SLionel Sambuc     if (private_key->private_key.rsa == NULL) {
832ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
833ebfedea0SLionel Sambuc 			       "Failed to generate RSA key");
834ebfedea0SLionel Sambuc 	return HX509_PARSING_KEY_FAILED;
835ebfedea0SLionel Sambuc     }
836ebfedea0SLionel Sambuc 
837ebfedea0SLionel Sambuc     e = BN_new();
838ebfedea0SLionel Sambuc     BN_set_word(e, default_rsa_e);
839ebfedea0SLionel Sambuc 
840ebfedea0SLionel Sambuc     bits = default_rsa_bits;
841ebfedea0SLionel Sambuc 
842ebfedea0SLionel Sambuc     if (ctx->num_bits)
843ebfedea0SLionel Sambuc 	bits = ctx->num_bits;
844ebfedea0SLionel Sambuc 
845ebfedea0SLionel Sambuc     ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL);
846ebfedea0SLionel Sambuc     BN_free(e);
847ebfedea0SLionel Sambuc     if (ret != 1) {
848ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
849ebfedea0SLionel Sambuc 			       "Failed to generate RSA key");
850ebfedea0SLionel Sambuc 	return HX509_PARSING_KEY_FAILED;
851ebfedea0SLionel Sambuc     }
852ebfedea0SLionel Sambuc     private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
853ebfedea0SLionel Sambuc 
854ebfedea0SLionel Sambuc     return 0;
855ebfedea0SLionel Sambuc }
856ebfedea0SLionel Sambuc 
857ebfedea0SLionel Sambuc static int
rsa_private_key_export(hx509_context context,const hx509_private_key key,hx509_key_format_t format,heim_octet_string * data)858ebfedea0SLionel Sambuc rsa_private_key_export(hx509_context context,
859ebfedea0SLionel Sambuc 		       const hx509_private_key key,
860ebfedea0SLionel Sambuc 		       hx509_key_format_t format,
861ebfedea0SLionel Sambuc 		       heim_octet_string *data)
862ebfedea0SLionel Sambuc {
863ebfedea0SLionel Sambuc     int ret;
864ebfedea0SLionel Sambuc 
865ebfedea0SLionel Sambuc     data->data = NULL;
866ebfedea0SLionel Sambuc     data->length = 0;
867ebfedea0SLionel Sambuc 
868ebfedea0SLionel Sambuc     switch (format) {
869ebfedea0SLionel Sambuc     case HX509_KEY_FORMAT_DER:
870ebfedea0SLionel Sambuc 
871ebfedea0SLionel Sambuc 	ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL);
872ebfedea0SLionel Sambuc 	if (ret <= 0) {
873ebfedea0SLionel Sambuc 	    ret = EINVAL;
874ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret,
875ebfedea0SLionel Sambuc 			       "Private key is not exportable");
876ebfedea0SLionel Sambuc 	    return ret;
877ebfedea0SLionel Sambuc 	}
878ebfedea0SLionel Sambuc 
879ebfedea0SLionel Sambuc 	data->data = malloc(ret);
880ebfedea0SLionel Sambuc 	if (data->data == NULL) {
881ebfedea0SLionel Sambuc 	    ret = ENOMEM;
882ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, ret, "malloc out of memory");
883ebfedea0SLionel Sambuc 	    return ret;
884ebfedea0SLionel Sambuc 	}
885ebfedea0SLionel Sambuc 	data->length = ret;
886ebfedea0SLionel Sambuc 
887ebfedea0SLionel Sambuc 	{
888ebfedea0SLionel Sambuc 	    unsigned char *p = data->data;
889ebfedea0SLionel Sambuc 	    i2d_RSAPrivateKey(key->private_key.rsa, &p);
890ebfedea0SLionel Sambuc 	}
891ebfedea0SLionel Sambuc 	break;
892ebfedea0SLionel Sambuc     default:
893ebfedea0SLionel Sambuc 	return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
894ebfedea0SLionel Sambuc     }
895ebfedea0SLionel Sambuc 
896ebfedea0SLionel Sambuc     return 0;
897ebfedea0SLionel Sambuc }
898ebfedea0SLionel Sambuc 
899ebfedea0SLionel Sambuc static BIGNUM *
rsa_get_internal(hx509_context context,hx509_private_key key,const char * type)900ebfedea0SLionel Sambuc rsa_get_internal(hx509_context context,
901ebfedea0SLionel Sambuc 		 hx509_private_key key,
902ebfedea0SLionel Sambuc 		 const char *type)
903ebfedea0SLionel Sambuc {
904ebfedea0SLionel Sambuc     if (strcasecmp(type, "rsa-modulus") == 0) {
905ebfedea0SLionel Sambuc 	return BN_dup(key->private_key.rsa->n);
906ebfedea0SLionel Sambuc     } else if (strcasecmp(type, "rsa-exponent") == 0) {
907ebfedea0SLionel Sambuc 	return BN_dup(key->private_key.rsa->e);
908ebfedea0SLionel Sambuc     } else
909ebfedea0SLionel Sambuc 	return NULL;
910ebfedea0SLionel Sambuc }
911ebfedea0SLionel Sambuc 
912ebfedea0SLionel Sambuc 
913ebfedea0SLionel Sambuc 
914ebfedea0SLionel Sambuc static hx509_private_key_ops rsa_private_key_ops = {
915ebfedea0SLionel Sambuc     "RSA PRIVATE KEY",
916ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
917ebfedea0SLionel Sambuc     NULL,
918ebfedea0SLionel Sambuc     rsa_private_key2SPKI,
919ebfedea0SLionel Sambuc     rsa_private_key_export,
920ebfedea0SLionel Sambuc     rsa_private_key_import,
921ebfedea0SLionel Sambuc     rsa_generate_private_key,
922ebfedea0SLionel Sambuc     rsa_get_internal
923ebfedea0SLionel Sambuc };
924ebfedea0SLionel Sambuc 
925ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
926ebfedea0SLionel Sambuc 
927ebfedea0SLionel Sambuc static int
ecdsa_private_key2SPKI(hx509_context context,hx509_private_key private_key,SubjectPublicKeyInfo * spki)928ebfedea0SLionel Sambuc ecdsa_private_key2SPKI(hx509_context context,
929ebfedea0SLionel Sambuc 		       hx509_private_key private_key,
930ebfedea0SLionel Sambuc 		       SubjectPublicKeyInfo *spki)
931ebfedea0SLionel Sambuc {
932ebfedea0SLionel Sambuc     memset(spki, 0, sizeof(*spki));
933ebfedea0SLionel Sambuc     return ENOMEM;
934ebfedea0SLionel Sambuc }
935ebfedea0SLionel Sambuc 
936ebfedea0SLionel Sambuc static int
ecdsa_private_key_export(hx509_context context,const hx509_private_key key,hx509_key_format_t format,heim_octet_string * data)937ebfedea0SLionel Sambuc ecdsa_private_key_export(hx509_context context,
938ebfedea0SLionel Sambuc 			 const hx509_private_key key,
939ebfedea0SLionel Sambuc 			 hx509_key_format_t format,
940ebfedea0SLionel Sambuc 			 heim_octet_string *data)
941ebfedea0SLionel Sambuc {
942ebfedea0SLionel Sambuc     return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
943ebfedea0SLionel Sambuc }
944ebfedea0SLionel Sambuc 
945ebfedea0SLionel Sambuc static int
ecdsa_private_key_import(hx509_context context,const AlgorithmIdentifier * keyai,const void * data,size_t len,hx509_key_format_t format,hx509_private_key private_key)946ebfedea0SLionel Sambuc ecdsa_private_key_import(hx509_context context,
947ebfedea0SLionel Sambuc 			 const AlgorithmIdentifier *keyai,
948ebfedea0SLionel Sambuc 			 const void *data,
949ebfedea0SLionel Sambuc 			 size_t len,
950ebfedea0SLionel Sambuc 			 hx509_key_format_t format,
951ebfedea0SLionel Sambuc 			 hx509_private_key private_key)
952ebfedea0SLionel Sambuc {
953ebfedea0SLionel Sambuc     const unsigned char *p = data;
954ebfedea0SLionel Sambuc     EC_KEY **pkey = NULL;
955ebfedea0SLionel Sambuc 
956ebfedea0SLionel Sambuc     if (keyai->parameters) {
957ebfedea0SLionel Sambuc 	EC_GROUP *group;
958ebfedea0SLionel Sambuc 	int groupnid;
959ebfedea0SLionel Sambuc 	EC_KEY *key;
960ebfedea0SLionel Sambuc 	int ret;
961ebfedea0SLionel Sambuc 
962ebfedea0SLionel Sambuc 	ret = parse_ECParameters(context, keyai->parameters, &groupnid);
963ebfedea0SLionel Sambuc 	if (ret)
964ebfedea0SLionel Sambuc 	    return ret;
965ebfedea0SLionel Sambuc 
966ebfedea0SLionel Sambuc 	key = EC_KEY_new();
967ebfedea0SLionel Sambuc 	if (key == NULL)
968ebfedea0SLionel Sambuc 	    return ENOMEM;
969ebfedea0SLionel Sambuc 
970ebfedea0SLionel Sambuc 	group = EC_GROUP_new_by_curve_name(groupnid);
971ebfedea0SLionel Sambuc 	if (group == NULL) {
972ebfedea0SLionel Sambuc 	    EC_KEY_free(key);
973ebfedea0SLionel Sambuc 	    return ENOMEM;
974ebfedea0SLionel Sambuc 	}
975ebfedea0SLionel Sambuc 	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
976ebfedea0SLionel Sambuc 	if (EC_KEY_set_group(key, group) == 0) {
977ebfedea0SLionel Sambuc 	    EC_KEY_free(key);
978ebfedea0SLionel Sambuc 	    EC_GROUP_free(group);
979ebfedea0SLionel Sambuc 	    return ENOMEM;
980ebfedea0SLionel Sambuc 	}
981ebfedea0SLionel Sambuc 	EC_GROUP_free(group);
982ebfedea0SLionel Sambuc 	pkey = &key;
983ebfedea0SLionel Sambuc     }
984ebfedea0SLionel Sambuc 
985ebfedea0SLionel Sambuc     switch (format) {
986ebfedea0SLionel Sambuc     case HX509_KEY_FORMAT_DER:
987ebfedea0SLionel Sambuc 
988ebfedea0SLionel Sambuc 	private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
989ebfedea0SLionel Sambuc 	if (private_key->private_key.ecdsa == NULL) {
990ebfedea0SLionel Sambuc 	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
991ebfedea0SLionel Sambuc 				   "Failed to parse EC private key");
992ebfedea0SLionel Sambuc 	    return HX509_PARSING_KEY_FAILED;
993ebfedea0SLionel Sambuc 	}
994ebfedea0SLionel Sambuc 	private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
995ebfedea0SLionel Sambuc 	break;
996ebfedea0SLionel Sambuc 
997ebfedea0SLionel Sambuc     default:
998ebfedea0SLionel Sambuc 	return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
999ebfedea0SLionel Sambuc     }
1000ebfedea0SLionel Sambuc 
1001ebfedea0SLionel Sambuc     return 0;
1002ebfedea0SLionel Sambuc }
1003ebfedea0SLionel Sambuc 
1004ebfedea0SLionel Sambuc static int
ecdsa_generate_private_key(hx509_context context,struct hx509_generate_private_context * ctx,hx509_private_key private_key)1005ebfedea0SLionel Sambuc ecdsa_generate_private_key(hx509_context context,
1006ebfedea0SLionel Sambuc 			   struct hx509_generate_private_context *ctx,
1007ebfedea0SLionel Sambuc 			   hx509_private_key private_key)
1008ebfedea0SLionel Sambuc {
1009ebfedea0SLionel Sambuc     return ENOMEM;
1010ebfedea0SLionel Sambuc }
1011ebfedea0SLionel Sambuc 
1012ebfedea0SLionel Sambuc static BIGNUM *
ecdsa_get_internal(hx509_context context,hx509_private_key key,const char * type)1013ebfedea0SLionel Sambuc ecdsa_get_internal(hx509_context context,
1014ebfedea0SLionel Sambuc 		   hx509_private_key key,
1015ebfedea0SLionel Sambuc 		   const char *type)
1016ebfedea0SLionel Sambuc {
1017ebfedea0SLionel Sambuc     return NULL;
1018ebfedea0SLionel Sambuc }
1019ebfedea0SLionel Sambuc 
1020ebfedea0SLionel Sambuc 
1021ebfedea0SLionel Sambuc static hx509_private_key_ops ecdsa_private_key_ops = {
1022ebfedea0SLionel Sambuc     "EC PRIVATE KEY",
1023ebfedea0SLionel Sambuc     ASN1_OID_ID_ECPUBLICKEY,
1024ebfedea0SLionel Sambuc     ecdsa_available,
1025ebfedea0SLionel Sambuc     ecdsa_private_key2SPKI,
1026ebfedea0SLionel Sambuc     ecdsa_private_key_export,
1027ebfedea0SLionel Sambuc     ecdsa_private_key_import,
1028ebfedea0SLionel Sambuc     ecdsa_generate_private_key,
1029ebfedea0SLionel Sambuc     ecdsa_get_internal
1030ebfedea0SLionel Sambuc };
1031ebfedea0SLionel Sambuc 
1032ebfedea0SLionel Sambuc #endif /* HAVE_OPENSSL */
1033ebfedea0SLionel Sambuc 
1034ebfedea0SLionel Sambuc /*
1035ebfedea0SLionel Sambuc  *
1036ebfedea0SLionel Sambuc  */
1037ebfedea0SLionel Sambuc 
1038ebfedea0SLionel Sambuc static int
dsa_verify_signature(hx509_context context,const struct signature_alg * sig_alg,const Certificate * signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)1039ebfedea0SLionel Sambuc dsa_verify_signature(hx509_context context,
1040ebfedea0SLionel Sambuc 		     const struct signature_alg *sig_alg,
1041ebfedea0SLionel Sambuc 		     const Certificate *signer,
1042ebfedea0SLionel Sambuc 		     const AlgorithmIdentifier *alg,
1043ebfedea0SLionel Sambuc 		     const heim_octet_string *data,
1044ebfedea0SLionel Sambuc 		     const heim_octet_string *sig)
1045ebfedea0SLionel Sambuc {
1046ebfedea0SLionel Sambuc     const SubjectPublicKeyInfo *spi;
1047ebfedea0SLionel Sambuc     DSAPublicKey pk;
1048ebfedea0SLionel Sambuc     DSAParams param;
1049ebfedea0SLionel Sambuc     size_t size;
1050ebfedea0SLionel Sambuc     DSA *dsa;
1051ebfedea0SLionel Sambuc     int ret;
1052ebfedea0SLionel Sambuc 
1053ebfedea0SLionel Sambuc     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
1054ebfedea0SLionel Sambuc 
1055ebfedea0SLionel Sambuc     dsa = DSA_new();
1056ebfedea0SLionel Sambuc     if (dsa == NULL) {
1057ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1058ebfedea0SLionel Sambuc 	return ENOMEM;
1059ebfedea0SLionel Sambuc     }
1060ebfedea0SLionel Sambuc 
1061ebfedea0SLionel Sambuc     ret = decode_DSAPublicKey(spi->subjectPublicKey.data,
1062ebfedea0SLionel Sambuc 			      spi->subjectPublicKey.length / 8,
1063ebfedea0SLionel Sambuc 			      &pk, &size);
1064ebfedea0SLionel Sambuc     if (ret)
1065ebfedea0SLionel Sambuc 	goto out;
1066ebfedea0SLionel Sambuc 
1067ebfedea0SLionel Sambuc     dsa->pub_key = heim_int2BN(&pk);
1068ebfedea0SLionel Sambuc 
1069ebfedea0SLionel Sambuc     free_DSAPublicKey(&pk);
1070ebfedea0SLionel Sambuc 
1071ebfedea0SLionel Sambuc     if (dsa->pub_key == NULL) {
1072ebfedea0SLionel Sambuc 	ret = ENOMEM;
1073ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
1074ebfedea0SLionel Sambuc 	goto out;
1075ebfedea0SLionel Sambuc     }
1076ebfedea0SLionel Sambuc 
1077ebfedea0SLionel Sambuc     if (spi->algorithm.parameters == NULL) {
1078ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
1079ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "DSA parameters missing");
1080ebfedea0SLionel Sambuc 	goto out;
1081ebfedea0SLionel Sambuc     }
1082ebfedea0SLionel Sambuc 
1083ebfedea0SLionel Sambuc     ret = decode_DSAParams(spi->algorithm.parameters->data,
1084ebfedea0SLionel Sambuc 			   spi->algorithm.parameters->length,
1085ebfedea0SLionel Sambuc 			   &param,
1086ebfedea0SLionel Sambuc 			   &size);
1087ebfedea0SLionel Sambuc     if (ret) {
1088ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode");
1089ebfedea0SLionel Sambuc 	goto out;
1090ebfedea0SLionel Sambuc     }
1091ebfedea0SLionel Sambuc 
1092ebfedea0SLionel Sambuc     dsa->p = heim_int2BN(&param.p);
1093ebfedea0SLionel Sambuc     dsa->q = heim_int2BN(&param.q);
1094ebfedea0SLionel Sambuc     dsa->g = heim_int2BN(&param.g);
1095ebfedea0SLionel Sambuc 
1096ebfedea0SLionel Sambuc     free_DSAParams(&param);
1097ebfedea0SLionel Sambuc 
1098ebfedea0SLionel Sambuc     if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
1099ebfedea0SLionel Sambuc 	ret = ENOMEM;
1100ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
1101ebfedea0SLionel Sambuc 	goto out;
1102ebfedea0SLionel Sambuc     }
1103ebfedea0SLionel Sambuc 
1104ebfedea0SLionel Sambuc     ret = DSA_verify(-1, data->data, data->length,
1105ebfedea0SLionel Sambuc 		     (unsigned char*)sig->data, sig->length,
1106ebfedea0SLionel Sambuc 		     dsa);
1107ebfedea0SLionel Sambuc     if (ret == 1)
1108ebfedea0SLionel Sambuc 	ret = 0;
1109ebfedea0SLionel Sambuc     else if (ret == 0 || ret == -1) {
1110ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_BAD_SIGNATURE;
1111ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "BAD DSA sigature");
1112ebfedea0SLionel Sambuc     } else {
1113ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
1114ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature");
1115ebfedea0SLionel Sambuc     }
1116ebfedea0SLionel Sambuc 
1117ebfedea0SLionel Sambuc  out:
1118ebfedea0SLionel Sambuc     DSA_free(dsa);
1119ebfedea0SLionel Sambuc 
1120ebfedea0SLionel Sambuc     return ret;
1121ebfedea0SLionel Sambuc }
1122ebfedea0SLionel Sambuc 
1123ebfedea0SLionel Sambuc #if 0
1124ebfedea0SLionel Sambuc static int
1125ebfedea0SLionel Sambuc dsa_parse_private_key(hx509_context context,
1126ebfedea0SLionel Sambuc 		      const void *data,
1127ebfedea0SLionel Sambuc 		      size_t len,
1128ebfedea0SLionel Sambuc 		      hx509_private_key private_key)
1129ebfedea0SLionel Sambuc {
1130ebfedea0SLionel Sambuc     const unsigned char *p = data;
1131ebfedea0SLionel Sambuc 
1132ebfedea0SLionel Sambuc     private_key->private_key.dsa =
1133ebfedea0SLionel Sambuc 	d2i_DSAPrivateKey(NULL, &p, len);
1134ebfedea0SLionel Sambuc     if (private_key->private_key.dsa == NULL)
1135ebfedea0SLionel Sambuc 	return EINVAL;
1136ebfedea0SLionel Sambuc     private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1;
1137ebfedea0SLionel Sambuc 
1138ebfedea0SLionel Sambuc     return 0;
1139ebfedea0SLionel Sambuc /* else */
1140ebfedea0SLionel Sambuc     hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
1141ebfedea0SLionel Sambuc 			   "No support to parse DSA keys");
1142ebfedea0SLionel Sambuc     return HX509_PARSING_KEY_FAILED;
1143ebfedea0SLionel Sambuc }
1144ebfedea0SLionel Sambuc #endif
1145ebfedea0SLionel Sambuc 
1146ebfedea0SLionel Sambuc static int
evp_md_create_signature(hx509_context context,const struct signature_alg * sig_alg,const hx509_private_key signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,AlgorithmIdentifier * signatureAlgorithm,heim_octet_string * sig)1147ebfedea0SLionel Sambuc evp_md_create_signature(hx509_context context,
1148ebfedea0SLionel Sambuc 			const struct signature_alg *sig_alg,
1149ebfedea0SLionel Sambuc 			const hx509_private_key signer,
1150ebfedea0SLionel Sambuc 			const AlgorithmIdentifier *alg,
1151ebfedea0SLionel Sambuc 			const heim_octet_string *data,
1152ebfedea0SLionel Sambuc 			AlgorithmIdentifier *signatureAlgorithm,
1153ebfedea0SLionel Sambuc 			heim_octet_string *sig)
1154ebfedea0SLionel Sambuc {
1155ebfedea0SLionel Sambuc     size_t sigsize = EVP_MD_size(sig_alg->evp_md());
1156ebfedea0SLionel Sambuc     EVP_MD_CTX *ctx;
1157ebfedea0SLionel Sambuc 
1158ebfedea0SLionel Sambuc     memset(sig, 0, sizeof(*sig));
1159ebfedea0SLionel Sambuc 
1160ebfedea0SLionel Sambuc     if (signatureAlgorithm) {
1161ebfedea0SLionel Sambuc 	int ret;
1162ebfedea0SLionel Sambuc 	ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
1163ebfedea0SLionel Sambuc 			     "\x05\x00", 2);
1164ebfedea0SLionel Sambuc 	if (ret)
1165ebfedea0SLionel Sambuc 	    return ret;
1166ebfedea0SLionel Sambuc     }
1167ebfedea0SLionel Sambuc 
1168ebfedea0SLionel Sambuc 
1169ebfedea0SLionel Sambuc     sig->data = malloc(sigsize);
1170ebfedea0SLionel Sambuc     if (sig->data == NULL) {
1171ebfedea0SLionel Sambuc 	sig->length = 0;
1172ebfedea0SLionel Sambuc 	return ENOMEM;
1173ebfedea0SLionel Sambuc     }
1174ebfedea0SLionel Sambuc     sig->length = sigsize;
1175ebfedea0SLionel Sambuc 
1176ebfedea0SLionel Sambuc     ctx = EVP_MD_CTX_create();
1177ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);
1178ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, data->data, data->length);
1179ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, sig->data, NULL);
1180ebfedea0SLionel Sambuc     EVP_MD_CTX_destroy(ctx);
1181ebfedea0SLionel Sambuc 
1182ebfedea0SLionel Sambuc 
1183ebfedea0SLionel Sambuc     return 0;
1184ebfedea0SLionel Sambuc }
1185ebfedea0SLionel Sambuc 
1186ebfedea0SLionel Sambuc static int
evp_md_verify_signature(hx509_context context,const struct signature_alg * sig_alg,const Certificate * signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)1187ebfedea0SLionel Sambuc evp_md_verify_signature(hx509_context context,
1188ebfedea0SLionel Sambuc 			const struct signature_alg *sig_alg,
1189ebfedea0SLionel Sambuc 			const Certificate *signer,
1190ebfedea0SLionel Sambuc 			const AlgorithmIdentifier *alg,
1191ebfedea0SLionel Sambuc 			const heim_octet_string *data,
1192ebfedea0SLionel Sambuc 			const heim_octet_string *sig)
1193ebfedea0SLionel Sambuc {
1194ebfedea0SLionel Sambuc     unsigned char digest[EVP_MAX_MD_SIZE];
1195ebfedea0SLionel Sambuc     EVP_MD_CTX *ctx;
1196ebfedea0SLionel Sambuc     size_t sigsize = EVP_MD_size(sig_alg->evp_md());
1197ebfedea0SLionel Sambuc 
1198ebfedea0SLionel Sambuc     if (sig->length != sigsize || sigsize > sizeof(digest)) {
1199ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
1200ebfedea0SLionel Sambuc 			       "SHA256 sigature have wrong length");
1201ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
1202ebfedea0SLionel Sambuc     }
1203ebfedea0SLionel Sambuc 
1204ebfedea0SLionel Sambuc     ctx = EVP_MD_CTX_create();
1205ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);
1206ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, data->data, data->length);
1207ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, digest, NULL);
1208ebfedea0SLionel Sambuc     EVP_MD_CTX_destroy(ctx);
1209ebfedea0SLionel Sambuc 
1210ebfedea0SLionel Sambuc     if (ct_memcmp(digest, sig->data, sigsize) != 0) {
1211ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE,
1212ebfedea0SLionel Sambuc 			       "Bad %s sigature", sig_alg->name);
1213ebfedea0SLionel Sambuc 	return HX509_CRYPTO_BAD_SIGNATURE;
1214ebfedea0SLionel Sambuc     }
1215ebfedea0SLionel Sambuc 
1216ebfedea0SLionel Sambuc     return 0;
1217ebfedea0SLionel Sambuc }
1218ebfedea0SLionel Sambuc 
1219ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
1220ebfedea0SLionel Sambuc 
1221ebfedea0SLionel Sambuc static const struct signature_alg ecdsa_with_sha256_alg = {
1222ebfedea0SLionel Sambuc     "ecdsa-with-sha256",
1223ebfedea0SLionel Sambuc     ASN1_OID_ID_ECDSA_WITH_SHA256,
1224ebfedea0SLionel Sambuc     &_hx509_signature_ecdsa_with_sha256_data,
1225ebfedea0SLionel Sambuc     ASN1_OID_ID_ECPUBLICKEY,
1226ebfedea0SLionel Sambuc     &_hx509_signature_sha256_data,
1227ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1228ebfedea0SLionel Sambuc     0,
1229ebfedea0SLionel Sambuc     NULL,
1230ebfedea0SLionel Sambuc     ecdsa_verify_signature,
1231ebfedea0SLionel Sambuc     ecdsa_create_signature,
1232ebfedea0SLionel Sambuc     32
1233ebfedea0SLionel Sambuc };
1234ebfedea0SLionel Sambuc 
1235ebfedea0SLionel Sambuc static const struct signature_alg ecdsa_with_sha1_alg = {
1236ebfedea0SLionel Sambuc     "ecdsa-with-sha1",
1237ebfedea0SLionel Sambuc     ASN1_OID_ID_ECDSA_WITH_SHA1,
1238ebfedea0SLionel Sambuc     &_hx509_signature_ecdsa_with_sha1_data,
1239ebfedea0SLionel Sambuc     ASN1_OID_ID_ECPUBLICKEY,
1240ebfedea0SLionel Sambuc     &_hx509_signature_sha1_data,
1241ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1242ebfedea0SLionel Sambuc     0,
1243ebfedea0SLionel Sambuc     NULL,
1244ebfedea0SLionel Sambuc     ecdsa_verify_signature,
1245ebfedea0SLionel Sambuc     ecdsa_create_signature,
1246ebfedea0SLionel Sambuc     20
1247ebfedea0SLionel Sambuc };
1248ebfedea0SLionel Sambuc 
1249ebfedea0SLionel Sambuc #endif
1250ebfedea0SLionel Sambuc 
1251ebfedea0SLionel Sambuc static const struct signature_alg heim_rsa_pkcs1_x509 = {
1252ebfedea0SLionel Sambuc     "rsa-pkcs1-x509",
1253ebfedea0SLionel Sambuc     ASN1_OID_ID_HEIM_RSA_PKCS1_X509,
1254ebfedea0SLionel Sambuc     &_hx509_signature_rsa_pkcs1_x509_data,
1255ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1256ebfedea0SLionel Sambuc     NULL,
1257ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
1258ebfedea0SLionel Sambuc     0,
1259ebfedea0SLionel Sambuc     NULL,
1260ebfedea0SLionel Sambuc     rsa_verify_signature,
1261*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1262*0a6a1f1dSLionel Sambuc     0
1263ebfedea0SLionel Sambuc };
1264ebfedea0SLionel Sambuc 
1265ebfedea0SLionel Sambuc static const struct signature_alg pkcs1_rsa_sha1_alg = {
1266ebfedea0SLionel Sambuc     "rsa",
1267ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1268ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha1_data,
1269ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1270ebfedea0SLionel Sambuc     NULL,
1271ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1272ebfedea0SLionel Sambuc     0,
1273ebfedea0SLionel Sambuc     NULL,
1274ebfedea0SLionel Sambuc     rsa_verify_signature,
1275*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1276*0a6a1f1dSLionel Sambuc     0
1277ebfedea0SLionel Sambuc };
1278ebfedea0SLionel Sambuc 
1279ebfedea0SLionel Sambuc static const struct signature_alg rsa_with_sha512_alg = {
1280ebfedea0SLionel Sambuc     "rsa-with-sha512",
1281ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION,
1282ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha512_data,
1283ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1284ebfedea0SLionel Sambuc     &_hx509_signature_sha512_data,
1285ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1286ebfedea0SLionel Sambuc     0,
1287ebfedea0SLionel Sambuc     NULL,
1288ebfedea0SLionel Sambuc     rsa_verify_signature,
1289*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1290*0a6a1f1dSLionel Sambuc     0
1291ebfedea0SLionel Sambuc };
1292ebfedea0SLionel Sambuc 
1293ebfedea0SLionel Sambuc static const struct signature_alg rsa_with_sha384_alg = {
1294ebfedea0SLionel Sambuc     "rsa-with-sha384",
1295ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION,
1296ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha384_data,
1297ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1298ebfedea0SLionel Sambuc     &_hx509_signature_sha384_data,
1299ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1300ebfedea0SLionel Sambuc     0,
1301ebfedea0SLionel Sambuc     NULL,
1302ebfedea0SLionel Sambuc     rsa_verify_signature,
1303*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1304*0a6a1f1dSLionel Sambuc     0
1305ebfedea0SLionel Sambuc };
1306ebfedea0SLionel Sambuc 
1307ebfedea0SLionel Sambuc static const struct signature_alg rsa_with_sha256_alg = {
1308ebfedea0SLionel Sambuc     "rsa-with-sha256",
1309ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION,
1310ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha256_data,
1311ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1312ebfedea0SLionel Sambuc     &_hx509_signature_sha256_data,
1313ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1314ebfedea0SLionel Sambuc     0,
1315ebfedea0SLionel Sambuc     NULL,
1316ebfedea0SLionel Sambuc     rsa_verify_signature,
1317*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1318*0a6a1f1dSLionel Sambuc     0
1319ebfedea0SLionel Sambuc };
1320ebfedea0SLionel Sambuc 
1321ebfedea0SLionel Sambuc static const struct signature_alg rsa_with_sha1_alg = {
1322ebfedea0SLionel Sambuc     "rsa-with-sha1",
1323ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION,
1324ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha1_data,
1325ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1326ebfedea0SLionel Sambuc     &_hx509_signature_sha1_data,
1327ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1328ebfedea0SLionel Sambuc     0,
1329ebfedea0SLionel Sambuc     NULL,
1330ebfedea0SLionel Sambuc     rsa_verify_signature,
1331*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1332*0a6a1f1dSLionel Sambuc     0
1333ebfedea0SLionel Sambuc };
1334ebfedea0SLionel Sambuc 
1335ebfedea0SLionel Sambuc static const struct signature_alg rsa_with_sha1_alg_secsig = {
1336ebfedea0SLionel Sambuc     "rsa-with-sha1",
1337ebfedea0SLionel Sambuc     ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION,
1338ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha1_data,
1339ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1340ebfedea0SLionel Sambuc     &_hx509_signature_sha1_data,
1341ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1342ebfedea0SLionel Sambuc     0,
1343ebfedea0SLionel Sambuc     NULL,
1344ebfedea0SLionel Sambuc     rsa_verify_signature,
1345*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1346*0a6a1f1dSLionel Sambuc     0
1347ebfedea0SLionel Sambuc };
1348ebfedea0SLionel Sambuc 
1349ebfedea0SLionel Sambuc static const struct signature_alg rsa_with_md5_alg = {
1350ebfedea0SLionel Sambuc     "rsa-with-md5",
1351ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION,
1352ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_md5_data,
1353ebfedea0SLionel Sambuc     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1354ebfedea0SLionel Sambuc     &_hx509_signature_md5_data,
1355ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
1356ebfedea0SLionel Sambuc     1230739889,
1357ebfedea0SLionel Sambuc     NULL,
1358ebfedea0SLionel Sambuc     rsa_verify_signature,
1359*0a6a1f1dSLionel Sambuc     rsa_create_signature,
1360*0a6a1f1dSLionel Sambuc     0
1361ebfedea0SLionel Sambuc };
1362ebfedea0SLionel Sambuc 
1363ebfedea0SLionel Sambuc static const struct signature_alg dsa_sha1_alg = {
1364ebfedea0SLionel Sambuc     "dsa-with-sha1",
1365ebfedea0SLionel Sambuc     ASN1_OID_ID_DSA_WITH_SHA1,
1366ebfedea0SLionel Sambuc     NULL,
1367ebfedea0SLionel Sambuc     ASN1_OID_ID_DSA,
1368ebfedea0SLionel Sambuc     &_hx509_signature_sha1_data,
1369ebfedea0SLionel Sambuc     PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
1370ebfedea0SLionel Sambuc     0,
1371ebfedea0SLionel Sambuc     NULL,
1372ebfedea0SLionel Sambuc     dsa_verify_signature,
1373ebfedea0SLionel Sambuc     /* create_signature */ NULL,
1374*0a6a1f1dSLionel Sambuc     0
1375ebfedea0SLionel Sambuc };
1376ebfedea0SLionel Sambuc 
1377ebfedea0SLionel Sambuc static const struct signature_alg sha512_alg = {
1378ebfedea0SLionel Sambuc     "sha-512",
1379ebfedea0SLionel Sambuc     ASN1_OID_ID_SHA512,
1380ebfedea0SLionel Sambuc     &_hx509_signature_sha512_data,
1381ebfedea0SLionel Sambuc     NULL,
1382ebfedea0SLionel Sambuc     NULL,
1383ebfedea0SLionel Sambuc     SIG_DIGEST,
1384ebfedea0SLionel Sambuc     0,
1385ebfedea0SLionel Sambuc     EVP_sha512,
1386ebfedea0SLionel Sambuc     evp_md_verify_signature,
1387*0a6a1f1dSLionel Sambuc     evp_md_create_signature,
1388*0a6a1f1dSLionel Sambuc     0
1389ebfedea0SLionel Sambuc };
1390ebfedea0SLionel Sambuc 
1391ebfedea0SLionel Sambuc static const struct signature_alg sha384_alg = {
1392ebfedea0SLionel Sambuc     "sha-384",
1393ebfedea0SLionel Sambuc     ASN1_OID_ID_SHA512,
1394ebfedea0SLionel Sambuc     &_hx509_signature_sha384_data,
1395ebfedea0SLionel Sambuc     NULL,
1396ebfedea0SLionel Sambuc     NULL,
1397ebfedea0SLionel Sambuc     SIG_DIGEST,
1398ebfedea0SLionel Sambuc     0,
1399ebfedea0SLionel Sambuc     EVP_sha384,
1400ebfedea0SLionel Sambuc     evp_md_verify_signature,
1401*0a6a1f1dSLionel Sambuc     evp_md_create_signature,
1402*0a6a1f1dSLionel Sambuc     0
1403ebfedea0SLionel Sambuc };
1404ebfedea0SLionel Sambuc 
1405ebfedea0SLionel Sambuc static const struct signature_alg sha256_alg = {
1406ebfedea0SLionel Sambuc     "sha-256",
1407ebfedea0SLionel Sambuc     ASN1_OID_ID_SHA256,
1408ebfedea0SLionel Sambuc     &_hx509_signature_sha256_data,
1409ebfedea0SLionel Sambuc     NULL,
1410ebfedea0SLionel Sambuc     NULL,
1411ebfedea0SLionel Sambuc     SIG_DIGEST,
1412ebfedea0SLionel Sambuc     0,
1413ebfedea0SLionel Sambuc     EVP_sha256,
1414ebfedea0SLionel Sambuc     evp_md_verify_signature,
1415*0a6a1f1dSLionel Sambuc     evp_md_create_signature,
1416*0a6a1f1dSLionel Sambuc     0
1417ebfedea0SLionel Sambuc };
1418ebfedea0SLionel Sambuc 
1419ebfedea0SLionel Sambuc static const struct signature_alg sha1_alg = {
1420ebfedea0SLionel Sambuc     "sha1",
1421ebfedea0SLionel Sambuc     ASN1_OID_ID_SECSIG_SHA_1,
1422ebfedea0SLionel Sambuc     &_hx509_signature_sha1_data,
1423ebfedea0SLionel Sambuc     NULL,
1424ebfedea0SLionel Sambuc     NULL,
1425ebfedea0SLionel Sambuc     SIG_DIGEST,
1426ebfedea0SLionel Sambuc     0,
1427ebfedea0SLionel Sambuc     EVP_sha1,
1428ebfedea0SLionel Sambuc     evp_md_verify_signature,
1429*0a6a1f1dSLionel Sambuc     evp_md_create_signature,
1430*0a6a1f1dSLionel Sambuc     0
1431ebfedea0SLionel Sambuc };
1432ebfedea0SLionel Sambuc 
1433ebfedea0SLionel Sambuc static const struct signature_alg md5_alg = {
1434ebfedea0SLionel Sambuc     "rsa-md5",
1435ebfedea0SLionel Sambuc     ASN1_OID_ID_RSA_DIGEST_MD5,
1436ebfedea0SLionel Sambuc     &_hx509_signature_md5_data,
1437ebfedea0SLionel Sambuc     NULL,
1438ebfedea0SLionel Sambuc     NULL,
1439ebfedea0SLionel Sambuc     SIG_DIGEST,
1440ebfedea0SLionel Sambuc     0,
1441ebfedea0SLionel Sambuc     EVP_md5,
1442ebfedea0SLionel Sambuc     evp_md_verify_signature,
1443*0a6a1f1dSLionel Sambuc     NULL,
1444*0a6a1f1dSLionel Sambuc     0
1445ebfedea0SLionel Sambuc };
1446ebfedea0SLionel Sambuc 
1447ebfedea0SLionel Sambuc /*
1448ebfedea0SLionel Sambuc  * Order matter in this structure, "best" first for each "key
1449ebfedea0SLionel Sambuc  * compatible" type (type is ECDSA, RSA, DSA, none, etc)
1450ebfedea0SLionel Sambuc  */
1451ebfedea0SLionel Sambuc 
1452ebfedea0SLionel Sambuc static const struct signature_alg *sig_algs[] = {
1453ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
1454ebfedea0SLionel Sambuc     &ecdsa_with_sha256_alg,
1455ebfedea0SLionel Sambuc     &ecdsa_with_sha1_alg,
1456ebfedea0SLionel Sambuc #endif
1457ebfedea0SLionel Sambuc     &rsa_with_sha512_alg,
1458ebfedea0SLionel Sambuc     &rsa_with_sha384_alg,
1459ebfedea0SLionel Sambuc     &rsa_with_sha256_alg,
1460ebfedea0SLionel Sambuc     &rsa_with_sha1_alg,
1461ebfedea0SLionel Sambuc     &rsa_with_sha1_alg_secsig,
1462ebfedea0SLionel Sambuc     &pkcs1_rsa_sha1_alg,
1463ebfedea0SLionel Sambuc     &rsa_with_md5_alg,
1464ebfedea0SLionel Sambuc     &heim_rsa_pkcs1_x509,
1465ebfedea0SLionel Sambuc     &dsa_sha1_alg,
1466ebfedea0SLionel Sambuc     &sha512_alg,
1467ebfedea0SLionel Sambuc     &sha384_alg,
1468ebfedea0SLionel Sambuc     &sha256_alg,
1469ebfedea0SLionel Sambuc     &sha1_alg,
1470ebfedea0SLionel Sambuc     &md5_alg,
1471ebfedea0SLionel Sambuc     NULL
1472ebfedea0SLionel Sambuc };
1473ebfedea0SLionel Sambuc 
1474ebfedea0SLionel Sambuc static const struct signature_alg *
find_sig_alg(const heim_oid * oid)1475ebfedea0SLionel Sambuc find_sig_alg(const heim_oid *oid)
1476ebfedea0SLionel Sambuc {
1477ebfedea0SLionel Sambuc     unsigned int i;
1478ebfedea0SLionel Sambuc     for (i = 0; sig_algs[i]; i++)
1479ebfedea0SLionel Sambuc 	if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0)
1480ebfedea0SLionel Sambuc 	    return sig_algs[i];
1481ebfedea0SLionel Sambuc     return NULL;
1482ebfedea0SLionel Sambuc }
1483ebfedea0SLionel Sambuc 
1484ebfedea0SLionel Sambuc static const AlgorithmIdentifier *
alg_for_privatekey(const hx509_private_key pk,int type)1485ebfedea0SLionel Sambuc alg_for_privatekey(const hx509_private_key pk, int type)
1486ebfedea0SLionel Sambuc {
1487ebfedea0SLionel Sambuc     const heim_oid *keytype;
1488ebfedea0SLionel Sambuc     unsigned int i;
1489ebfedea0SLionel Sambuc 
1490ebfedea0SLionel Sambuc     if (pk->ops == NULL)
1491ebfedea0SLionel Sambuc 	return NULL;
1492ebfedea0SLionel Sambuc 
1493ebfedea0SLionel Sambuc     keytype = pk->ops->key_oid;
1494ebfedea0SLionel Sambuc 
1495ebfedea0SLionel Sambuc     for (i = 0; sig_algs[i]; i++) {
1496ebfedea0SLionel Sambuc 	if (sig_algs[i]->key_oid == NULL)
1497ebfedea0SLionel Sambuc 	    continue;
1498ebfedea0SLionel Sambuc 	if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0)
1499ebfedea0SLionel Sambuc 	    continue;
1500ebfedea0SLionel Sambuc 	if (pk->ops->available &&
1501ebfedea0SLionel Sambuc 	    pk->ops->available(pk, sig_algs[i]->sig_alg) == 0)
1502ebfedea0SLionel Sambuc 	    continue;
1503ebfedea0SLionel Sambuc 	if (type == HX509_SELECT_PUBLIC_SIG)
1504ebfedea0SLionel Sambuc 	    return sig_algs[i]->sig_alg;
1505ebfedea0SLionel Sambuc 	if (type == HX509_SELECT_DIGEST)
1506ebfedea0SLionel Sambuc 	    return sig_algs[i]->digest_alg;
1507ebfedea0SLionel Sambuc 
1508ebfedea0SLionel Sambuc 	return NULL;
1509ebfedea0SLionel Sambuc     }
1510ebfedea0SLionel Sambuc     return NULL;
1511ebfedea0SLionel Sambuc }
1512ebfedea0SLionel Sambuc 
1513ebfedea0SLionel Sambuc /*
1514ebfedea0SLionel Sambuc  *
1515ebfedea0SLionel Sambuc  */
1516ebfedea0SLionel Sambuc 
1517ebfedea0SLionel Sambuc static struct hx509_private_key_ops *private_algs[] = {
1518ebfedea0SLionel Sambuc     &rsa_private_key_ops,
1519ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
1520ebfedea0SLionel Sambuc     &ecdsa_private_key_ops,
1521ebfedea0SLionel Sambuc #endif
1522ebfedea0SLionel Sambuc     NULL
1523ebfedea0SLionel Sambuc };
1524ebfedea0SLionel Sambuc 
1525ebfedea0SLionel Sambuc hx509_private_key_ops *
hx509_find_private_alg(const heim_oid * oid)1526ebfedea0SLionel Sambuc hx509_find_private_alg(const heim_oid *oid)
1527ebfedea0SLionel Sambuc {
1528ebfedea0SLionel Sambuc     int i;
1529ebfedea0SLionel Sambuc     for (i = 0; private_algs[i]; i++) {
1530ebfedea0SLionel Sambuc 	if (private_algs[i]->key_oid == NULL)
1531ebfedea0SLionel Sambuc 	    continue;
1532ebfedea0SLionel Sambuc 	if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0)
1533ebfedea0SLionel Sambuc 	    return private_algs[i];
1534ebfedea0SLionel Sambuc     }
1535ebfedea0SLionel Sambuc     return NULL;
1536ebfedea0SLionel Sambuc }
1537ebfedea0SLionel Sambuc 
1538ebfedea0SLionel Sambuc /*
1539ebfedea0SLionel Sambuc  * Check if the algorithm `alg' have a best before date, and if it
1540ebfedea0SLionel Sambuc  * des, make sure the its before the time `t'.
1541ebfedea0SLionel Sambuc  */
1542ebfedea0SLionel Sambuc 
1543ebfedea0SLionel Sambuc int
_hx509_signature_best_before(hx509_context context,const AlgorithmIdentifier * alg,time_t t)1544ebfedea0SLionel Sambuc _hx509_signature_best_before(hx509_context context,
1545ebfedea0SLionel Sambuc 			     const AlgorithmIdentifier *alg,
1546ebfedea0SLionel Sambuc 			     time_t t)
1547ebfedea0SLionel Sambuc {
1548ebfedea0SLionel Sambuc     const struct signature_alg *md;
1549ebfedea0SLionel Sambuc 
1550ebfedea0SLionel Sambuc     md = find_sig_alg(&alg->algorithm);
1551ebfedea0SLionel Sambuc     if (md == NULL) {
1552ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
1553ebfedea0SLionel Sambuc 	return HX509_SIG_ALG_NO_SUPPORTED;
1554ebfedea0SLionel Sambuc     }
1555ebfedea0SLionel Sambuc     if (md->best_before && md->best_before < t) {
1556ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
1557ebfedea0SLionel Sambuc 			       "Algorithm %s has passed it best before date",
1558ebfedea0SLionel Sambuc 			       md->name);
1559ebfedea0SLionel Sambuc 	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
1560ebfedea0SLionel Sambuc     }
1561ebfedea0SLionel Sambuc     return 0;
1562ebfedea0SLionel Sambuc }
1563ebfedea0SLionel Sambuc 
1564ebfedea0SLionel Sambuc int
_hx509_self_signed_valid(hx509_context context,const AlgorithmIdentifier * alg)1565ebfedea0SLionel Sambuc _hx509_self_signed_valid(hx509_context context,
1566ebfedea0SLionel Sambuc 			 const AlgorithmIdentifier *alg)
1567ebfedea0SLionel Sambuc {
1568ebfedea0SLionel Sambuc     const struct signature_alg *md;
1569ebfedea0SLionel Sambuc 
1570ebfedea0SLionel Sambuc     md = find_sig_alg(&alg->algorithm);
1571ebfedea0SLionel Sambuc     if (md == NULL) {
1572ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
1573ebfedea0SLionel Sambuc 	return HX509_SIG_ALG_NO_SUPPORTED;
1574ebfedea0SLionel Sambuc     }
1575ebfedea0SLionel Sambuc     if ((md->flags & SELF_SIGNED_OK) == 0) {
1576ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
1577ebfedea0SLionel Sambuc 			       "Algorithm %s not trusted for self signatures",
1578ebfedea0SLionel Sambuc 			       md->name);
1579ebfedea0SLionel Sambuc 	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
1580ebfedea0SLionel Sambuc     }
1581ebfedea0SLionel Sambuc     return 0;
1582ebfedea0SLionel Sambuc }
1583ebfedea0SLionel Sambuc 
1584ebfedea0SLionel Sambuc 
1585ebfedea0SLionel Sambuc int
_hx509_verify_signature(hx509_context context,const hx509_cert cert,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)1586ebfedea0SLionel Sambuc _hx509_verify_signature(hx509_context context,
1587ebfedea0SLionel Sambuc 			const hx509_cert cert,
1588ebfedea0SLionel Sambuc 			const AlgorithmIdentifier *alg,
1589ebfedea0SLionel Sambuc 			const heim_octet_string *data,
1590ebfedea0SLionel Sambuc 			const heim_octet_string *sig)
1591ebfedea0SLionel Sambuc {
1592ebfedea0SLionel Sambuc     const struct signature_alg *md;
1593ebfedea0SLionel Sambuc     const Certificate *signer = NULL;
1594ebfedea0SLionel Sambuc 
1595ebfedea0SLionel Sambuc     if (cert)
1596ebfedea0SLionel Sambuc 	signer = _hx509_get_cert(cert);
1597ebfedea0SLionel Sambuc 
1598ebfedea0SLionel Sambuc     md = find_sig_alg(&alg->algorithm);
1599ebfedea0SLionel Sambuc     if (md == NULL) {
1600ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
1601ebfedea0SLionel Sambuc 	return HX509_SIG_ALG_NO_SUPPORTED;
1602ebfedea0SLionel Sambuc     }
1603ebfedea0SLionel Sambuc     if (signer && (md->flags & PROVIDE_CONF) == 0) {
1604ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
1605ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_NO_CONF;
1606ebfedea0SLionel Sambuc     }
1607ebfedea0SLionel Sambuc     if (signer == NULL && (md->flags & REQUIRE_SIGNER)) {
1608ebfedea0SLionel Sambuc 	    hx509_clear_error_string(context);
1609ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER;
1610ebfedea0SLionel Sambuc     }
1611ebfedea0SLionel Sambuc     if (md->key_oid && signer) {
1612ebfedea0SLionel Sambuc 	const SubjectPublicKeyInfo *spi;
1613ebfedea0SLionel Sambuc 	spi = &signer->tbsCertificate.subjectPublicKeyInfo;
1614ebfedea0SLionel Sambuc 
1615ebfedea0SLionel Sambuc 	if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) {
1616ebfedea0SLionel Sambuc 	    hx509_clear_error_string(context);
1617ebfedea0SLionel Sambuc 	    return HX509_SIG_ALG_DONT_MATCH_KEY_ALG;
1618ebfedea0SLionel Sambuc 	}
1619ebfedea0SLionel Sambuc     }
1620ebfedea0SLionel Sambuc     return (*md->verify_signature)(context, md, signer, alg, data, sig);
1621ebfedea0SLionel Sambuc }
1622ebfedea0SLionel Sambuc 
1623ebfedea0SLionel Sambuc int
_hx509_create_signature(hx509_context context,const hx509_private_key signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,AlgorithmIdentifier * signatureAlgorithm,heim_octet_string * sig)1624ebfedea0SLionel Sambuc _hx509_create_signature(hx509_context context,
1625ebfedea0SLionel Sambuc 			const hx509_private_key signer,
1626ebfedea0SLionel Sambuc 			const AlgorithmIdentifier *alg,
1627ebfedea0SLionel Sambuc 			const heim_octet_string *data,
1628ebfedea0SLionel Sambuc 			AlgorithmIdentifier *signatureAlgorithm,
1629ebfedea0SLionel Sambuc 			heim_octet_string *sig)
1630ebfedea0SLionel Sambuc {
1631ebfedea0SLionel Sambuc     const struct signature_alg *md;
1632ebfedea0SLionel Sambuc 
1633ebfedea0SLionel Sambuc     md = find_sig_alg(&alg->algorithm);
1634ebfedea0SLionel Sambuc     if (md == NULL) {
1635ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
1636ebfedea0SLionel Sambuc 	    "algorithm no supported");
1637ebfedea0SLionel Sambuc 	return HX509_SIG_ALG_NO_SUPPORTED;
1638ebfedea0SLionel Sambuc     }
1639ebfedea0SLionel Sambuc 
1640ebfedea0SLionel Sambuc     if (signer && (md->flags & PROVIDE_CONF) == 0) {
1641ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
1642ebfedea0SLionel Sambuc 	    "algorithm provides no conf");
1643ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_NO_CONF;
1644ebfedea0SLionel Sambuc     }
1645ebfedea0SLionel Sambuc 
1646ebfedea0SLionel Sambuc     return (*md->create_signature)(context, md, signer, alg, data,
1647ebfedea0SLionel Sambuc 				   signatureAlgorithm, sig);
1648ebfedea0SLionel Sambuc }
1649ebfedea0SLionel Sambuc 
1650ebfedea0SLionel Sambuc int
_hx509_create_signature_bitstring(hx509_context context,const hx509_private_key signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,AlgorithmIdentifier * signatureAlgorithm,heim_bit_string * sig)1651ebfedea0SLionel Sambuc _hx509_create_signature_bitstring(hx509_context context,
1652ebfedea0SLionel Sambuc 				  const hx509_private_key signer,
1653ebfedea0SLionel Sambuc 				  const AlgorithmIdentifier *alg,
1654ebfedea0SLionel Sambuc 				  const heim_octet_string *data,
1655ebfedea0SLionel Sambuc 				  AlgorithmIdentifier *signatureAlgorithm,
1656ebfedea0SLionel Sambuc 				  heim_bit_string *sig)
1657ebfedea0SLionel Sambuc {
1658ebfedea0SLionel Sambuc     heim_octet_string os;
1659ebfedea0SLionel Sambuc     int ret;
1660ebfedea0SLionel Sambuc 
1661ebfedea0SLionel Sambuc     ret = _hx509_create_signature(context, signer, alg,
1662ebfedea0SLionel Sambuc 				  data, signatureAlgorithm, &os);
1663ebfedea0SLionel Sambuc     if (ret)
1664ebfedea0SLionel Sambuc 	return ret;
1665ebfedea0SLionel Sambuc     sig->data = os.data;
1666ebfedea0SLionel Sambuc     sig->length = os.length * 8;
1667ebfedea0SLionel Sambuc     return 0;
1668ebfedea0SLionel Sambuc }
1669ebfedea0SLionel Sambuc 
1670ebfedea0SLionel Sambuc int
_hx509_public_encrypt(hx509_context context,const heim_octet_string * cleartext,const Certificate * cert,heim_oid * encryption_oid,heim_octet_string * ciphertext)1671ebfedea0SLionel Sambuc _hx509_public_encrypt(hx509_context context,
1672ebfedea0SLionel Sambuc 		      const heim_octet_string *cleartext,
1673ebfedea0SLionel Sambuc 		      const Certificate *cert,
1674ebfedea0SLionel Sambuc 		      heim_oid *encryption_oid,
1675ebfedea0SLionel Sambuc 		      heim_octet_string *ciphertext)
1676ebfedea0SLionel Sambuc {
1677ebfedea0SLionel Sambuc     const SubjectPublicKeyInfo *spi;
1678ebfedea0SLionel Sambuc     unsigned char *to;
1679ebfedea0SLionel Sambuc     int tosize;
1680ebfedea0SLionel Sambuc     int ret;
1681ebfedea0SLionel Sambuc     RSA *rsa;
1682ebfedea0SLionel Sambuc     size_t size;
1683ebfedea0SLionel Sambuc     const unsigned char *p;
1684ebfedea0SLionel Sambuc 
1685ebfedea0SLionel Sambuc     ciphertext->data = NULL;
1686ebfedea0SLionel Sambuc     ciphertext->length = 0;
1687ebfedea0SLionel Sambuc 
1688ebfedea0SLionel Sambuc     spi = &cert->tbsCertificate.subjectPublicKeyInfo;
1689ebfedea0SLionel Sambuc 
1690ebfedea0SLionel Sambuc     p = spi->subjectPublicKey.data;
1691ebfedea0SLionel Sambuc     size = spi->subjectPublicKey.length / 8;
1692ebfedea0SLionel Sambuc 
1693ebfedea0SLionel Sambuc     rsa = d2i_RSAPublicKey(NULL, &p, size);
1694ebfedea0SLionel Sambuc     if (rsa == NULL) {
1695ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1696ebfedea0SLionel Sambuc 	return ENOMEM;
1697ebfedea0SLionel Sambuc     }
1698ebfedea0SLionel Sambuc 
1699ebfedea0SLionel Sambuc     tosize = RSA_size(rsa);
1700ebfedea0SLionel Sambuc     to = malloc(tosize);
1701ebfedea0SLionel Sambuc     if (to == NULL) {
1702ebfedea0SLionel Sambuc 	RSA_free(rsa);
1703ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1704ebfedea0SLionel Sambuc 	return ENOMEM;
1705ebfedea0SLionel Sambuc     }
1706ebfedea0SLionel Sambuc 
1707ebfedea0SLionel Sambuc     ret = RSA_public_encrypt(cleartext->length,
1708ebfedea0SLionel Sambuc 			     (unsigned char *)cleartext->data,
1709ebfedea0SLionel Sambuc 			     to, rsa, RSA_PKCS1_PADDING);
1710ebfedea0SLionel Sambuc     RSA_free(rsa);
1711ebfedea0SLionel Sambuc     if (ret <= 0) {
1712ebfedea0SLionel Sambuc 	free(to);
1713ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT,
1714ebfedea0SLionel Sambuc 			       "RSA public encrypt failed with %d", ret);
1715ebfedea0SLionel Sambuc 	return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT;
1716ebfedea0SLionel Sambuc     }
1717ebfedea0SLionel Sambuc     if (ret > tosize)
1718ebfedea0SLionel Sambuc 	_hx509_abort("internal rsa decryption failure: ret > tosize");
1719ebfedea0SLionel Sambuc 
1720ebfedea0SLionel Sambuc     ciphertext->length = ret;
1721ebfedea0SLionel Sambuc     ciphertext->data = to;
1722ebfedea0SLionel Sambuc 
1723ebfedea0SLionel Sambuc     ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid);
1724ebfedea0SLionel Sambuc     if (ret) {
1725ebfedea0SLionel Sambuc 	der_free_octet_string(ciphertext);
1726ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1727ebfedea0SLionel Sambuc 	return ENOMEM;
1728ebfedea0SLionel Sambuc     }
1729ebfedea0SLionel Sambuc 
1730ebfedea0SLionel Sambuc     return 0;
1731ebfedea0SLionel Sambuc }
1732ebfedea0SLionel Sambuc 
1733ebfedea0SLionel Sambuc int
hx509_private_key_private_decrypt(hx509_context context,const heim_octet_string * ciphertext,const heim_oid * encryption_oid,hx509_private_key p,heim_octet_string * cleartext)1734ebfedea0SLionel Sambuc hx509_private_key_private_decrypt(hx509_context context,
1735ebfedea0SLionel Sambuc 				   const heim_octet_string *ciphertext,
1736ebfedea0SLionel Sambuc 				   const heim_oid *encryption_oid,
1737ebfedea0SLionel Sambuc 				   hx509_private_key p,
1738ebfedea0SLionel Sambuc 				   heim_octet_string *cleartext)
1739ebfedea0SLionel Sambuc {
1740ebfedea0SLionel Sambuc     int ret;
1741ebfedea0SLionel Sambuc 
1742ebfedea0SLionel Sambuc     cleartext->data = NULL;
1743ebfedea0SLionel Sambuc     cleartext->length = 0;
1744ebfedea0SLionel Sambuc 
1745ebfedea0SLionel Sambuc     if (p->private_key.rsa == NULL) {
1746ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1747ebfedea0SLionel Sambuc 			       "Private RSA key missing");
1748ebfedea0SLionel Sambuc 	return HX509_PRIVATE_KEY_MISSING;
1749ebfedea0SLionel Sambuc     }
1750ebfedea0SLionel Sambuc 
1751ebfedea0SLionel Sambuc     cleartext->length = RSA_size(p->private_key.rsa);
1752ebfedea0SLionel Sambuc     cleartext->data = malloc(cleartext->length);
1753ebfedea0SLionel Sambuc     if (cleartext->data == NULL) {
1754ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1755ebfedea0SLionel Sambuc 	return ENOMEM;
1756ebfedea0SLionel Sambuc     }
1757ebfedea0SLionel Sambuc     ret = RSA_private_decrypt(ciphertext->length, ciphertext->data,
1758ebfedea0SLionel Sambuc 			      cleartext->data,
1759ebfedea0SLionel Sambuc 			      p->private_key.rsa,
1760ebfedea0SLionel Sambuc 			      RSA_PKCS1_PADDING);
1761ebfedea0SLionel Sambuc     if (ret <= 0) {
1762ebfedea0SLionel Sambuc 	der_free_octet_string(cleartext);
1763ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT,
1764ebfedea0SLionel Sambuc 			       "Failed to decrypt using private key: %d", ret);
1765ebfedea0SLionel Sambuc 	return HX509_CRYPTO_RSA_PRIVATE_DECRYPT;
1766ebfedea0SLionel Sambuc     }
1767*0a6a1f1dSLionel Sambuc     if (cleartext->length < (size_t)ret)
1768ebfedea0SLionel Sambuc 	_hx509_abort("internal rsa decryption failure: ret > tosize");
1769ebfedea0SLionel Sambuc 
1770ebfedea0SLionel Sambuc     cleartext->length = ret;
1771ebfedea0SLionel Sambuc 
1772ebfedea0SLionel Sambuc     return 0;
1773ebfedea0SLionel Sambuc }
1774ebfedea0SLionel Sambuc 
1775ebfedea0SLionel Sambuc 
1776ebfedea0SLionel Sambuc int
hx509_parse_private_key(hx509_context context,const AlgorithmIdentifier * keyai,const void * data,size_t len,hx509_key_format_t format,hx509_private_key * private_key)1777ebfedea0SLionel Sambuc hx509_parse_private_key(hx509_context context,
1778ebfedea0SLionel Sambuc 			 const AlgorithmIdentifier *keyai,
1779ebfedea0SLionel Sambuc 			 const void *data,
1780ebfedea0SLionel Sambuc 			 size_t len,
1781ebfedea0SLionel Sambuc 			 hx509_key_format_t format,
1782ebfedea0SLionel Sambuc 			 hx509_private_key *private_key)
1783ebfedea0SLionel Sambuc {
1784ebfedea0SLionel Sambuc     struct hx509_private_key_ops *ops;
1785ebfedea0SLionel Sambuc     int ret;
1786ebfedea0SLionel Sambuc 
1787ebfedea0SLionel Sambuc     *private_key = NULL;
1788ebfedea0SLionel Sambuc 
1789ebfedea0SLionel Sambuc     ops = hx509_find_private_alg(&keyai->algorithm);
1790ebfedea0SLionel Sambuc     if (ops == NULL) {
1791ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
1792ebfedea0SLionel Sambuc 	return HX509_SIG_ALG_NO_SUPPORTED;
1793ebfedea0SLionel Sambuc     }
1794ebfedea0SLionel Sambuc 
1795ebfedea0SLionel Sambuc     ret = hx509_private_key_init(private_key, ops, NULL);
1796ebfedea0SLionel Sambuc     if (ret) {
1797ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
1798ebfedea0SLionel Sambuc 	return ret;
1799ebfedea0SLionel Sambuc     }
1800ebfedea0SLionel Sambuc 
1801ebfedea0SLionel Sambuc     ret = (*ops->import)(context, keyai, data, len, format, *private_key);
1802ebfedea0SLionel Sambuc     if (ret)
1803ebfedea0SLionel Sambuc 	hx509_private_key_free(private_key);
1804ebfedea0SLionel Sambuc 
1805ebfedea0SLionel Sambuc     return ret;
1806ebfedea0SLionel Sambuc }
1807ebfedea0SLionel Sambuc 
1808ebfedea0SLionel Sambuc /*
1809ebfedea0SLionel Sambuc  *
1810ebfedea0SLionel Sambuc  */
1811ebfedea0SLionel Sambuc 
1812ebfedea0SLionel Sambuc int
hx509_private_key2SPKI(hx509_context context,hx509_private_key private_key,SubjectPublicKeyInfo * spki)1813ebfedea0SLionel Sambuc hx509_private_key2SPKI(hx509_context context,
1814ebfedea0SLionel Sambuc 			hx509_private_key private_key,
1815ebfedea0SLionel Sambuc 			SubjectPublicKeyInfo *spki)
1816ebfedea0SLionel Sambuc {
1817ebfedea0SLionel Sambuc     const struct hx509_private_key_ops *ops = private_key->ops;
1818ebfedea0SLionel Sambuc     if (ops == NULL || ops->get_spki == NULL) {
1819ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
1820ebfedea0SLionel Sambuc 			       "Private key have no key2SPKI function");
1821ebfedea0SLionel Sambuc 	return HX509_UNIMPLEMENTED_OPERATION;
1822ebfedea0SLionel Sambuc     }
1823ebfedea0SLionel Sambuc     return (*ops->get_spki)(context, private_key, spki);
1824ebfedea0SLionel Sambuc }
1825ebfedea0SLionel Sambuc 
1826ebfedea0SLionel Sambuc int
_hx509_generate_private_key_init(hx509_context context,const heim_oid * oid,struct hx509_generate_private_context ** ctx)1827ebfedea0SLionel Sambuc _hx509_generate_private_key_init(hx509_context context,
1828ebfedea0SLionel Sambuc 				 const heim_oid *oid,
1829ebfedea0SLionel Sambuc 				 struct hx509_generate_private_context **ctx)
1830ebfedea0SLionel Sambuc {
1831ebfedea0SLionel Sambuc     *ctx = NULL;
1832ebfedea0SLionel Sambuc 
1833ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) {
1834ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, EINVAL,
1835ebfedea0SLionel Sambuc 			       "private key not an RSA key");
1836ebfedea0SLionel Sambuc 	return EINVAL;
1837ebfedea0SLionel Sambuc     }
1838ebfedea0SLionel Sambuc 
1839ebfedea0SLionel Sambuc     *ctx = calloc(1, sizeof(**ctx));
1840ebfedea0SLionel Sambuc     if (*ctx == NULL) {
1841ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1842ebfedea0SLionel Sambuc 	return ENOMEM;
1843ebfedea0SLionel Sambuc     }
1844ebfedea0SLionel Sambuc     (*ctx)->key_oid = oid;
1845ebfedea0SLionel Sambuc 
1846ebfedea0SLionel Sambuc     return 0;
1847ebfedea0SLionel Sambuc }
1848ebfedea0SLionel Sambuc 
1849ebfedea0SLionel Sambuc int
_hx509_generate_private_key_is_ca(hx509_context context,struct hx509_generate_private_context * ctx)1850ebfedea0SLionel Sambuc _hx509_generate_private_key_is_ca(hx509_context context,
1851ebfedea0SLionel Sambuc 				  struct hx509_generate_private_context *ctx)
1852ebfedea0SLionel Sambuc {
1853ebfedea0SLionel Sambuc     ctx->isCA = 1;
1854ebfedea0SLionel Sambuc     return 0;
1855ebfedea0SLionel Sambuc }
1856ebfedea0SLionel Sambuc 
1857ebfedea0SLionel Sambuc int
_hx509_generate_private_key_bits(hx509_context context,struct hx509_generate_private_context * ctx,unsigned long bits)1858ebfedea0SLionel Sambuc _hx509_generate_private_key_bits(hx509_context context,
1859ebfedea0SLionel Sambuc 				 struct hx509_generate_private_context *ctx,
1860ebfedea0SLionel Sambuc 				 unsigned long bits)
1861ebfedea0SLionel Sambuc {
1862ebfedea0SLionel Sambuc     ctx->num_bits = bits;
1863ebfedea0SLionel Sambuc     return 0;
1864ebfedea0SLionel Sambuc }
1865ebfedea0SLionel Sambuc 
1866ebfedea0SLionel Sambuc 
1867ebfedea0SLionel Sambuc void
_hx509_generate_private_key_free(struct hx509_generate_private_context ** ctx)1868ebfedea0SLionel Sambuc _hx509_generate_private_key_free(struct hx509_generate_private_context **ctx)
1869ebfedea0SLionel Sambuc {
1870ebfedea0SLionel Sambuc     free(*ctx);
1871ebfedea0SLionel Sambuc     *ctx = NULL;
1872ebfedea0SLionel Sambuc }
1873ebfedea0SLionel Sambuc 
1874ebfedea0SLionel Sambuc int
_hx509_generate_private_key(hx509_context context,struct hx509_generate_private_context * ctx,hx509_private_key * private_key)1875ebfedea0SLionel Sambuc _hx509_generate_private_key(hx509_context context,
1876ebfedea0SLionel Sambuc 			    struct hx509_generate_private_context *ctx,
1877ebfedea0SLionel Sambuc 			    hx509_private_key *private_key)
1878ebfedea0SLionel Sambuc {
1879ebfedea0SLionel Sambuc     struct hx509_private_key_ops *ops;
1880ebfedea0SLionel Sambuc     int ret;
1881ebfedea0SLionel Sambuc 
1882ebfedea0SLionel Sambuc     *private_key = NULL;
1883ebfedea0SLionel Sambuc 
1884ebfedea0SLionel Sambuc     ops = hx509_find_private_alg(ctx->key_oid);
1885ebfedea0SLionel Sambuc     if (ops == NULL) {
1886ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
1887ebfedea0SLionel Sambuc 	return HX509_SIG_ALG_NO_SUPPORTED;
1888ebfedea0SLionel Sambuc     }
1889ebfedea0SLionel Sambuc 
1890ebfedea0SLionel Sambuc     ret = hx509_private_key_init(private_key, ops, NULL);
1891ebfedea0SLionel Sambuc     if (ret) {
1892ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "out of memory");
1893ebfedea0SLionel Sambuc 	return ret;
1894ebfedea0SLionel Sambuc     }
1895ebfedea0SLionel Sambuc 
1896ebfedea0SLionel Sambuc     ret = (*ops->generate_private_key)(context, ctx, *private_key);
1897ebfedea0SLionel Sambuc     if (ret)
1898ebfedea0SLionel Sambuc 	hx509_private_key_free(private_key);
1899ebfedea0SLionel Sambuc 
1900ebfedea0SLionel Sambuc     return ret;
1901ebfedea0SLionel Sambuc }
1902ebfedea0SLionel Sambuc 
1903ebfedea0SLionel Sambuc /*
1904ebfedea0SLionel Sambuc  *
1905ebfedea0SLionel Sambuc  */
1906ebfedea0SLionel Sambuc 
1907ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_sha512(void)1908ebfedea0SLionel Sambuc hx509_signature_sha512(void)
1909ebfedea0SLionel Sambuc { return &_hx509_signature_sha512_data; }
1910ebfedea0SLionel Sambuc 
1911ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_sha384(void)1912ebfedea0SLionel Sambuc hx509_signature_sha384(void)
1913ebfedea0SLionel Sambuc { return &_hx509_signature_sha384_data; }
1914ebfedea0SLionel Sambuc 
1915ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_sha256(void)1916ebfedea0SLionel Sambuc hx509_signature_sha256(void)
1917ebfedea0SLionel Sambuc { return &_hx509_signature_sha256_data; }
1918ebfedea0SLionel Sambuc 
1919ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_sha1(void)1920ebfedea0SLionel Sambuc hx509_signature_sha1(void)
1921ebfedea0SLionel Sambuc { return &_hx509_signature_sha1_data; }
1922ebfedea0SLionel Sambuc 
1923ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_md5(void)1924ebfedea0SLionel Sambuc hx509_signature_md5(void)
1925ebfedea0SLionel Sambuc { return &_hx509_signature_md5_data; }
1926ebfedea0SLionel Sambuc 
1927ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_ecPublicKey(void)1928ebfedea0SLionel Sambuc hx509_signature_ecPublicKey(void)
1929ebfedea0SLionel Sambuc { return &_hx509_signature_ecPublicKey; }
1930ebfedea0SLionel Sambuc 
1931ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_ecdsa_with_sha256(void)1932ebfedea0SLionel Sambuc hx509_signature_ecdsa_with_sha256(void)
1933ebfedea0SLionel Sambuc { return &_hx509_signature_ecdsa_with_sha256_data; }
1934ebfedea0SLionel Sambuc 
1935ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_ecdsa_with_sha1(void)1936ebfedea0SLionel Sambuc hx509_signature_ecdsa_with_sha1(void)
1937ebfedea0SLionel Sambuc { return &_hx509_signature_ecdsa_with_sha1_data; }
1938ebfedea0SLionel Sambuc 
1939ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa_with_sha512(void)1940ebfedea0SLionel Sambuc hx509_signature_rsa_with_sha512(void)
1941ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_with_sha512_data; }
1942ebfedea0SLionel Sambuc 
1943ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa_with_sha384(void)1944ebfedea0SLionel Sambuc hx509_signature_rsa_with_sha384(void)
1945ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_with_sha384_data; }
1946ebfedea0SLionel Sambuc 
1947ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa_with_sha256(void)1948ebfedea0SLionel Sambuc hx509_signature_rsa_with_sha256(void)
1949ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_with_sha256_data; }
1950ebfedea0SLionel Sambuc 
1951ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa_with_sha1(void)1952ebfedea0SLionel Sambuc hx509_signature_rsa_with_sha1(void)
1953ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_with_sha1_data; }
1954ebfedea0SLionel Sambuc 
1955ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa_with_md5(void)1956ebfedea0SLionel Sambuc hx509_signature_rsa_with_md5(void)
1957ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_with_md5_data; }
1958ebfedea0SLionel Sambuc 
1959ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa(void)1960ebfedea0SLionel Sambuc hx509_signature_rsa(void)
1961ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_data; }
1962ebfedea0SLionel Sambuc 
1963ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_signature_rsa_pkcs1_x509(void)1964ebfedea0SLionel Sambuc hx509_signature_rsa_pkcs1_x509(void)
1965ebfedea0SLionel Sambuc { return &_hx509_signature_rsa_pkcs1_x509_data; }
1966ebfedea0SLionel Sambuc 
1967ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_crypto_des_rsdi_ede3_cbc(void)1968ebfedea0SLionel Sambuc hx509_crypto_des_rsdi_ede3_cbc(void)
1969ebfedea0SLionel Sambuc { return &_hx509_des_rsdi_ede3_cbc_oid; }
1970ebfedea0SLionel Sambuc 
1971ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_crypto_aes128_cbc(void)1972ebfedea0SLionel Sambuc hx509_crypto_aes128_cbc(void)
1973ebfedea0SLionel Sambuc { return &_hx509_crypto_aes128_cbc_data; }
1974ebfedea0SLionel Sambuc 
1975ebfedea0SLionel Sambuc const AlgorithmIdentifier *
hx509_crypto_aes256_cbc(void)1976ebfedea0SLionel Sambuc hx509_crypto_aes256_cbc(void)
1977ebfedea0SLionel Sambuc { return &_hx509_crypto_aes256_cbc_data; }
1978ebfedea0SLionel Sambuc 
1979ebfedea0SLionel Sambuc /*
1980ebfedea0SLionel Sambuc  *
1981ebfedea0SLionel Sambuc  */
1982ebfedea0SLionel Sambuc 
1983ebfedea0SLionel Sambuc const AlgorithmIdentifier * _hx509_crypto_default_sig_alg =
1984ebfedea0SLionel Sambuc     &_hx509_signature_rsa_with_sha256_data;
1985ebfedea0SLionel Sambuc const AlgorithmIdentifier * _hx509_crypto_default_digest_alg =
1986ebfedea0SLionel Sambuc     &_hx509_signature_sha256_data;
1987ebfedea0SLionel Sambuc const AlgorithmIdentifier * _hx509_crypto_default_secret_alg =
1988ebfedea0SLionel Sambuc     &_hx509_crypto_aes128_cbc_data;
1989ebfedea0SLionel Sambuc 
1990ebfedea0SLionel Sambuc /*
1991ebfedea0SLionel Sambuc  *
1992ebfedea0SLionel Sambuc  */
1993ebfedea0SLionel Sambuc 
1994ebfedea0SLionel Sambuc int
hx509_private_key_init(hx509_private_key * key,hx509_private_key_ops * ops,void * keydata)1995ebfedea0SLionel Sambuc hx509_private_key_init(hx509_private_key *key,
1996ebfedea0SLionel Sambuc 			hx509_private_key_ops *ops,
1997ebfedea0SLionel Sambuc 			void *keydata)
1998ebfedea0SLionel Sambuc {
1999ebfedea0SLionel Sambuc     *key = calloc(1, sizeof(**key));
2000ebfedea0SLionel Sambuc     if (*key == NULL)
2001ebfedea0SLionel Sambuc 	return ENOMEM;
2002ebfedea0SLionel Sambuc     (*key)->ref = 1;
2003ebfedea0SLionel Sambuc     (*key)->ops = ops;
2004ebfedea0SLionel Sambuc     (*key)->private_key.keydata = keydata;
2005ebfedea0SLionel Sambuc     return 0;
2006ebfedea0SLionel Sambuc }
2007ebfedea0SLionel Sambuc 
2008ebfedea0SLionel Sambuc hx509_private_key
_hx509_private_key_ref(hx509_private_key key)2009ebfedea0SLionel Sambuc _hx509_private_key_ref(hx509_private_key key)
2010ebfedea0SLionel Sambuc {
2011ebfedea0SLionel Sambuc     if (key->ref == 0)
2012ebfedea0SLionel Sambuc 	_hx509_abort("key refcount <= 0 on ref");
2013ebfedea0SLionel Sambuc     key->ref++;
2014ebfedea0SLionel Sambuc     if (key->ref == UINT_MAX)
2015ebfedea0SLionel Sambuc 	_hx509_abort("key refcount == UINT_MAX on ref");
2016ebfedea0SLionel Sambuc     return key;
2017ebfedea0SLionel Sambuc }
2018ebfedea0SLionel Sambuc 
2019ebfedea0SLionel Sambuc const char *
_hx509_private_pem_name(hx509_private_key key)2020ebfedea0SLionel Sambuc _hx509_private_pem_name(hx509_private_key key)
2021ebfedea0SLionel Sambuc {
2022ebfedea0SLionel Sambuc     return key->ops->pemtype;
2023ebfedea0SLionel Sambuc }
2024ebfedea0SLionel Sambuc 
2025ebfedea0SLionel Sambuc int
hx509_private_key_free(hx509_private_key * key)2026ebfedea0SLionel Sambuc hx509_private_key_free(hx509_private_key *key)
2027ebfedea0SLionel Sambuc {
2028ebfedea0SLionel Sambuc     if (key == NULL || *key == NULL)
2029ebfedea0SLionel Sambuc 	return 0;
2030ebfedea0SLionel Sambuc 
2031ebfedea0SLionel Sambuc     if ((*key)->ref == 0)
2032ebfedea0SLionel Sambuc 	_hx509_abort("key refcount == 0 on free");
2033ebfedea0SLionel Sambuc     if (--(*key)->ref > 0)
2034ebfedea0SLionel Sambuc 	return 0;
2035ebfedea0SLionel Sambuc 
2036ebfedea0SLionel Sambuc     if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
2037ebfedea0SLionel Sambuc 	if ((*key)->private_key.rsa)
2038ebfedea0SLionel Sambuc 	    RSA_free((*key)->private_key.rsa);
2039ebfedea0SLionel Sambuc #ifdef HAVE_OPENSSL
2040ebfedea0SLionel Sambuc     } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) {
2041ebfedea0SLionel Sambuc 	if ((*key)->private_key.ecdsa)
2042ebfedea0SLionel Sambuc 	    EC_KEY_free((*key)->private_key.ecdsa);
2043ebfedea0SLionel Sambuc #endif
2044ebfedea0SLionel Sambuc     }
2045ebfedea0SLionel Sambuc     (*key)->private_key.rsa = NULL;
2046ebfedea0SLionel Sambuc     free(*key);
2047ebfedea0SLionel Sambuc     *key = NULL;
2048ebfedea0SLionel Sambuc     return 0;
2049ebfedea0SLionel Sambuc }
2050ebfedea0SLionel Sambuc 
2051ebfedea0SLionel Sambuc void
hx509_private_key_assign_rsa(hx509_private_key key,void * ptr)2052ebfedea0SLionel Sambuc hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
2053ebfedea0SLionel Sambuc {
2054ebfedea0SLionel Sambuc     if (key->private_key.rsa)
2055ebfedea0SLionel Sambuc 	RSA_free(key->private_key.rsa);
2056ebfedea0SLionel Sambuc     key->private_key.rsa = ptr;
2057ebfedea0SLionel Sambuc     key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
2058ebfedea0SLionel Sambuc     key->md = &pkcs1_rsa_sha1_alg;
2059ebfedea0SLionel Sambuc }
2060ebfedea0SLionel Sambuc 
2061ebfedea0SLionel Sambuc int
_hx509_private_key_oid(hx509_context context,const hx509_private_key key,heim_oid * data)2062ebfedea0SLionel Sambuc _hx509_private_key_oid(hx509_context context,
2063ebfedea0SLionel Sambuc 		       const hx509_private_key key,
2064ebfedea0SLionel Sambuc 		       heim_oid *data)
2065ebfedea0SLionel Sambuc {
2066ebfedea0SLionel Sambuc     int ret;
2067ebfedea0SLionel Sambuc     ret = der_copy_oid(key->ops->key_oid, data);
2068ebfedea0SLionel Sambuc     if (ret)
2069ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, ret, "malloc out of memory");
2070ebfedea0SLionel Sambuc     return ret;
2071ebfedea0SLionel Sambuc }
2072ebfedea0SLionel Sambuc 
2073ebfedea0SLionel Sambuc int
_hx509_private_key_exportable(hx509_private_key key)2074ebfedea0SLionel Sambuc _hx509_private_key_exportable(hx509_private_key key)
2075ebfedea0SLionel Sambuc {
2076ebfedea0SLionel Sambuc     if (key->ops->export == NULL)
2077ebfedea0SLionel Sambuc 	return 0;
2078ebfedea0SLionel Sambuc     return 1;
2079ebfedea0SLionel Sambuc }
2080ebfedea0SLionel Sambuc 
2081ebfedea0SLionel Sambuc BIGNUM *
_hx509_private_key_get_internal(hx509_context context,hx509_private_key key,const char * type)2082ebfedea0SLionel Sambuc _hx509_private_key_get_internal(hx509_context context,
2083ebfedea0SLionel Sambuc 				hx509_private_key key,
2084ebfedea0SLionel Sambuc 				const char *type)
2085ebfedea0SLionel Sambuc {
2086ebfedea0SLionel Sambuc     if (key->ops->get_internal == NULL)
2087ebfedea0SLionel Sambuc 	return NULL;
2088ebfedea0SLionel Sambuc     return (*key->ops->get_internal)(context, key, type);
2089ebfedea0SLionel Sambuc }
2090ebfedea0SLionel Sambuc 
2091ebfedea0SLionel Sambuc int
_hx509_private_key_export(hx509_context context,const hx509_private_key key,hx509_key_format_t format,heim_octet_string * data)2092ebfedea0SLionel Sambuc _hx509_private_key_export(hx509_context context,
2093ebfedea0SLionel Sambuc 			  const hx509_private_key key,
2094ebfedea0SLionel Sambuc 			  hx509_key_format_t format,
2095ebfedea0SLionel Sambuc 			  heim_octet_string *data)
2096ebfedea0SLionel Sambuc {
2097ebfedea0SLionel Sambuc     if (key->ops->export == NULL) {
2098ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2099ebfedea0SLionel Sambuc 	return HX509_UNIMPLEMENTED_OPERATION;
2100ebfedea0SLionel Sambuc     }
2101ebfedea0SLionel Sambuc     return (*key->ops->export)(context, key, format, data);
2102ebfedea0SLionel Sambuc }
2103ebfedea0SLionel Sambuc 
2104ebfedea0SLionel Sambuc /*
2105ebfedea0SLionel Sambuc  *
2106ebfedea0SLionel Sambuc  */
2107ebfedea0SLionel Sambuc 
2108ebfedea0SLionel Sambuc struct hx509cipher {
2109ebfedea0SLionel Sambuc     const char *name;
2110ebfedea0SLionel Sambuc     int flags;
2111ebfedea0SLionel Sambuc #define CIPHER_WEAK 1
2112ebfedea0SLionel Sambuc     const heim_oid *oid;
2113ebfedea0SLionel Sambuc     const AlgorithmIdentifier *(*ai_func)(void);
2114ebfedea0SLionel Sambuc     const EVP_CIPHER *(*evp_func)(void);
2115ebfedea0SLionel Sambuc     int (*get_params)(hx509_context, const hx509_crypto,
2116ebfedea0SLionel Sambuc 		      const heim_octet_string *, heim_octet_string *);
2117ebfedea0SLionel Sambuc     int (*set_params)(hx509_context, const heim_octet_string *,
2118ebfedea0SLionel Sambuc 		      hx509_crypto, heim_octet_string *);
2119ebfedea0SLionel Sambuc };
2120ebfedea0SLionel Sambuc 
2121ebfedea0SLionel Sambuc struct hx509_crypto_data {
2122ebfedea0SLionel Sambuc     char *name;
2123ebfedea0SLionel Sambuc     int flags;
2124ebfedea0SLionel Sambuc #define ALLOW_WEAK 	1
2125ebfedea0SLionel Sambuc 
2126ebfedea0SLionel Sambuc #define PADDING_NONE	2
2127ebfedea0SLionel Sambuc #define PADDING_PKCS7	4
2128ebfedea0SLionel Sambuc #define PADDING_FLAGS	(2|4)
2129ebfedea0SLionel Sambuc     const struct hx509cipher *cipher;
2130ebfedea0SLionel Sambuc     const EVP_CIPHER *c;
2131ebfedea0SLionel Sambuc     heim_octet_string key;
2132ebfedea0SLionel Sambuc     heim_oid oid;
2133ebfedea0SLionel Sambuc     void *param;
2134ebfedea0SLionel Sambuc };
2135ebfedea0SLionel Sambuc 
2136ebfedea0SLionel Sambuc /*
2137ebfedea0SLionel Sambuc  *
2138ebfedea0SLionel Sambuc  */
2139ebfedea0SLionel Sambuc 
2140ebfedea0SLionel Sambuc static unsigned private_rc2_40_oid_data[] = { 127, 1 };
2141ebfedea0SLionel Sambuc 
2142ebfedea0SLionel Sambuc static heim_oid asn1_oid_private_rc2_40 =
2143ebfedea0SLionel Sambuc     { 2, private_rc2_40_oid_data };
2144ebfedea0SLionel Sambuc 
2145ebfedea0SLionel Sambuc /*
2146ebfedea0SLionel Sambuc  *
2147ebfedea0SLionel Sambuc  */
2148ebfedea0SLionel Sambuc 
2149ebfedea0SLionel Sambuc static int
CMSCBCParam_get(hx509_context context,const hx509_crypto crypto,const heim_octet_string * ivec,heim_octet_string * param)2150ebfedea0SLionel Sambuc CMSCBCParam_get(hx509_context context, const hx509_crypto crypto,
2151ebfedea0SLionel Sambuc 		 const heim_octet_string *ivec, heim_octet_string *param)
2152ebfedea0SLionel Sambuc {
2153ebfedea0SLionel Sambuc     size_t size;
2154ebfedea0SLionel Sambuc     int ret;
2155ebfedea0SLionel Sambuc 
2156ebfedea0SLionel Sambuc     assert(crypto->param == NULL);
2157ebfedea0SLionel Sambuc     if (ivec == NULL)
2158ebfedea0SLionel Sambuc 	return 0;
2159ebfedea0SLionel Sambuc 
2160ebfedea0SLionel Sambuc     ASN1_MALLOC_ENCODE(CMSCBCParameter, param->data, param->length,
2161ebfedea0SLionel Sambuc 		       ivec, &size, ret);
2162ebfedea0SLionel Sambuc     if (ret == 0 && size != param->length)
2163ebfedea0SLionel Sambuc 	_hx509_abort("Internal asn1 encoder failure");
2164ebfedea0SLionel Sambuc     if (ret)
2165ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2166ebfedea0SLionel Sambuc     return ret;
2167ebfedea0SLionel Sambuc }
2168ebfedea0SLionel Sambuc 
2169ebfedea0SLionel Sambuc static int
CMSCBCParam_set(hx509_context context,const heim_octet_string * param,hx509_crypto crypto,heim_octet_string * ivec)2170ebfedea0SLionel Sambuc CMSCBCParam_set(hx509_context context, const heim_octet_string *param,
2171ebfedea0SLionel Sambuc 		hx509_crypto crypto, heim_octet_string *ivec)
2172ebfedea0SLionel Sambuc {
2173ebfedea0SLionel Sambuc     int ret;
2174ebfedea0SLionel Sambuc     if (ivec == NULL)
2175ebfedea0SLionel Sambuc 	return 0;
2176ebfedea0SLionel Sambuc 
2177ebfedea0SLionel Sambuc     ret = decode_CMSCBCParameter(param->data, param->length, ivec, NULL);
2178ebfedea0SLionel Sambuc     if (ret)
2179ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2180ebfedea0SLionel Sambuc 
2181ebfedea0SLionel Sambuc     return ret;
2182ebfedea0SLionel Sambuc }
2183ebfedea0SLionel Sambuc 
2184ebfedea0SLionel Sambuc struct _RC2_params {
2185ebfedea0SLionel Sambuc     int maximum_effective_key;
2186ebfedea0SLionel Sambuc };
2187ebfedea0SLionel Sambuc 
2188ebfedea0SLionel Sambuc static int
CMSRC2CBCParam_get(hx509_context context,const hx509_crypto crypto,const heim_octet_string * ivec,heim_octet_string * param)2189ebfedea0SLionel Sambuc CMSRC2CBCParam_get(hx509_context context, const hx509_crypto crypto,
2190ebfedea0SLionel Sambuc 		   const heim_octet_string *ivec, heim_octet_string *param)
2191ebfedea0SLionel Sambuc {
2192ebfedea0SLionel Sambuc     CMSRC2CBCParameter rc2params;
2193ebfedea0SLionel Sambuc     const struct _RC2_params *p = crypto->param;
2194ebfedea0SLionel Sambuc     int maximum_effective_key = 128;
2195ebfedea0SLionel Sambuc     size_t size;
2196ebfedea0SLionel Sambuc     int ret;
2197ebfedea0SLionel Sambuc 
2198ebfedea0SLionel Sambuc     memset(&rc2params, 0, sizeof(rc2params));
2199ebfedea0SLionel Sambuc 
2200ebfedea0SLionel Sambuc     if (p)
2201ebfedea0SLionel Sambuc 	maximum_effective_key = p->maximum_effective_key;
2202ebfedea0SLionel Sambuc 
2203ebfedea0SLionel Sambuc     switch(maximum_effective_key) {
2204ebfedea0SLionel Sambuc     case 40:
2205ebfedea0SLionel Sambuc 	rc2params.rc2ParameterVersion = 160;
2206ebfedea0SLionel Sambuc 	break;
2207ebfedea0SLionel Sambuc     case 64:
2208ebfedea0SLionel Sambuc 	rc2params.rc2ParameterVersion = 120;
2209ebfedea0SLionel Sambuc 	break;
2210ebfedea0SLionel Sambuc     case 128:
2211ebfedea0SLionel Sambuc 	rc2params.rc2ParameterVersion = 58;
2212ebfedea0SLionel Sambuc 	break;
2213ebfedea0SLionel Sambuc     }
2214ebfedea0SLionel Sambuc     rc2params.iv = *ivec;
2215ebfedea0SLionel Sambuc 
2216ebfedea0SLionel Sambuc     ASN1_MALLOC_ENCODE(CMSRC2CBCParameter, param->data, param->length,
2217ebfedea0SLionel Sambuc 		       &rc2params, &size, ret);
2218ebfedea0SLionel Sambuc     if (ret == 0 && size != param->length)
2219ebfedea0SLionel Sambuc 	_hx509_abort("Internal asn1 encoder failure");
2220ebfedea0SLionel Sambuc 
2221ebfedea0SLionel Sambuc     return ret;
2222ebfedea0SLionel Sambuc }
2223ebfedea0SLionel Sambuc 
2224ebfedea0SLionel Sambuc static int
CMSRC2CBCParam_set(hx509_context context,const heim_octet_string * param,hx509_crypto crypto,heim_octet_string * ivec)2225ebfedea0SLionel Sambuc CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
2226ebfedea0SLionel Sambuc 		   hx509_crypto crypto, heim_octet_string *ivec)
2227ebfedea0SLionel Sambuc {
2228ebfedea0SLionel Sambuc     CMSRC2CBCParameter rc2param;
2229ebfedea0SLionel Sambuc     struct _RC2_params *p;
2230ebfedea0SLionel Sambuc     size_t size;
2231ebfedea0SLionel Sambuc     int ret;
2232ebfedea0SLionel Sambuc 
2233ebfedea0SLionel Sambuc     ret = decode_CMSRC2CBCParameter(param->data, param->length,
2234ebfedea0SLionel Sambuc 				    &rc2param, &size);
2235ebfedea0SLionel Sambuc     if (ret) {
2236ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2237ebfedea0SLionel Sambuc 	return ret;
2238ebfedea0SLionel Sambuc     }
2239ebfedea0SLionel Sambuc 
2240ebfedea0SLionel Sambuc     p = calloc(1, sizeof(*p));
2241ebfedea0SLionel Sambuc     if (p == NULL) {
2242ebfedea0SLionel Sambuc 	free_CMSRC2CBCParameter(&rc2param);
2243ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2244ebfedea0SLionel Sambuc 	return ENOMEM;
2245ebfedea0SLionel Sambuc     }
2246ebfedea0SLionel Sambuc     switch(rc2param.rc2ParameterVersion) {
2247ebfedea0SLionel Sambuc     case 160:
2248ebfedea0SLionel Sambuc 	crypto->c = EVP_rc2_40_cbc();
2249ebfedea0SLionel Sambuc 	p->maximum_effective_key = 40;
2250ebfedea0SLionel Sambuc 	break;
2251ebfedea0SLionel Sambuc     case 120:
2252ebfedea0SLionel Sambuc 	crypto->c = EVP_rc2_64_cbc();
2253ebfedea0SLionel Sambuc 	p->maximum_effective_key = 64;
2254ebfedea0SLionel Sambuc 	break;
2255ebfedea0SLionel Sambuc     case 58:
2256ebfedea0SLionel Sambuc 	crypto->c = EVP_rc2_cbc();
2257ebfedea0SLionel Sambuc 	p->maximum_effective_key = 128;
2258ebfedea0SLionel Sambuc 	break;
2259ebfedea0SLionel Sambuc     default:
2260ebfedea0SLionel Sambuc 	free(p);
2261ebfedea0SLionel Sambuc 	free_CMSRC2CBCParameter(&rc2param);
2262ebfedea0SLionel Sambuc 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
2263ebfedea0SLionel Sambuc     }
2264ebfedea0SLionel Sambuc     if (ivec)
2265ebfedea0SLionel Sambuc 	ret = der_copy_octet_string(&rc2param.iv, ivec);
2266ebfedea0SLionel Sambuc     free_CMSRC2CBCParameter(&rc2param);
2267ebfedea0SLionel Sambuc     if (ret) {
2268ebfedea0SLionel Sambuc 	free(p);
2269ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2270ebfedea0SLionel Sambuc     } else
2271ebfedea0SLionel Sambuc 	crypto->param = p;
2272ebfedea0SLionel Sambuc 
2273ebfedea0SLionel Sambuc     return ret;
2274ebfedea0SLionel Sambuc }
2275ebfedea0SLionel Sambuc 
2276ebfedea0SLionel Sambuc /*
2277ebfedea0SLionel Sambuc  *
2278ebfedea0SLionel Sambuc  */
2279ebfedea0SLionel Sambuc 
2280ebfedea0SLionel Sambuc static const struct hx509cipher ciphers[] = {
2281ebfedea0SLionel Sambuc     {
2282ebfedea0SLionel Sambuc 	"rc2-cbc",
2283ebfedea0SLionel Sambuc 	CIPHER_WEAK,
2284ebfedea0SLionel Sambuc 	ASN1_OID_ID_PKCS3_RC2_CBC,
2285ebfedea0SLionel Sambuc 	NULL,
2286ebfedea0SLionel Sambuc 	EVP_rc2_cbc,
2287ebfedea0SLionel Sambuc 	CMSRC2CBCParam_get,
2288ebfedea0SLionel Sambuc 	CMSRC2CBCParam_set
2289ebfedea0SLionel Sambuc     },
2290ebfedea0SLionel Sambuc     {
2291ebfedea0SLionel Sambuc 	"rc2-cbc",
2292ebfedea0SLionel Sambuc 	CIPHER_WEAK,
2293ebfedea0SLionel Sambuc 	ASN1_OID_ID_RSADSI_RC2_CBC,
2294ebfedea0SLionel Sambuc 	NULL,
2295ebfedea0SLionel Sambuc 	EVP_rc2_cbc,
2296ebfedea0SLionel Sambuc 	CMSRC2CBCParam_get,
2297ebfedea0SLionel Sambuc 	CMSRC2CBCParam_set
2298ebfedea0SLionel Sambuc     },
2299ebfedea0SLionel Sambuc     {
2300ebfedea0SLionel Sambuc 	"rc2-40-cbc",
2301ebfedea0SLionel Sambuc 	CIPHER_WEAK,
2302ebfedea0SLionel Sambuc 	&asn1_oid_private_rc2_40,
2303ebfedea0SLionel Sambuc 	NULL,
2304ebfedea0SLionel Sambuc 	EVP_rc2_40_cbc,
2305ebfedea0SLionel Sambuc 	CMSRC2CBCParam_get,
2306ebfedea0SLionel Sambuc 	CMSRC2CBCParam_set
2307ebfedea0SLionel Sambuc     },
2308ebfedea0SLionel Sambuc     {
2309ebfedea0SLionel Sambuc 	"des-ede3-cbc",
2310ebfedea0SLionel Sambuc 	0,
2311ebfedea0SLionel Sambuc 	ASN1_OID_ID_PKCS3_DES_EDE3_CBC,
2312ebfedea0SLionel Sambuc 	NULL,
2313ebfedea0SLionel Sambuc 	EVP_des_ede3_cbc,
2314ebfedea0SLionel Sambuc 	CMSCBCParam_get,
2315ebfedea0SLionel Sambuc 	CMSCBCParam_set
2316ebfedea0SLionel Sambuc     },
2317ebfedea0SLionel Sambuc     {
2318ebfedea0SLionel Sambuc 	"des-ede3-cbc",
2319ebfedea0SLionel Sambuc 	0,
2320ebfedea0SLionel Sambuc 	ASN1_OID_ID_RSADSI_DES_EDE3_CBC,
2321ebfedea0SLionel Sambuc 	hx509_crypto_des_rsdi_ede3_cbc,
2322ebfedea0SLionel Sambuc 	EVP_des_ede3_cbc,
2323ebfedea0SLionel Sambuc 	CMSCBCParam_get,
2324ebfedea0SLionel Sambuc 	CMSCBCParam_set
2325ebfedea0SLionel Sambuc     },
2326ebfedea0SLionel Sambuc     {
2327ebfedea0SLionel Sambuc 	"aes-128-cbc",
2328ebfedea0SLionel Sambuc 	0,
2329ebfedea0SLionel Sambuc 	ASN1_OID_ID_AES_128_CBC,
2330ebfedea0SLionel Sambuc 	hx509_crypto_aes128_cbc,
2331ebfedea0SLionel Sambuc 	EVP_aes_128_cbc,
2332ebfedea0SLionel Sambuc 	CMSCBCParam_get,
2333ebfedea0SLionel Sambuc 	CMSCBCParam_set
2334ebfedea0SLionel Sambuc     },
2335ebfedea0SLionel Sambuc     {
2336ebfedea0SLionel Sambuc 	"aes-192-cbc",
2337ebfedea0SLionel Sambuc 	0,
2338ebfedea0SLionel Sambuc 	ASN1_OID_ID_AES_192_CBC,
2339ebfedea0SLionel Sambuc 	NULL,
2340ebfedea0SLionel Sambuc 	EVP_aes_192_cbc,
2341ebfedea0SLionel Sambuc 	CMSCBCParam_get,
2342ebfedea0SLionel Sambuc 	CMSCBCParam_set
2343ebfedea0SLionel Sambuc     },
2344ebfedea0SLionel Sambuc     {
2345ebfedea0SLionel Sambuc 	"aes-256-cbc",
2346ebfedea0SLionel Sambuc 	0,
2347ebfedea0SLionel Sambuc 	ASN1_OID_ID_AES_256_CBC,
2348ebfedea0SLionel Sambuc 	hx509_crypto_aes256_cbc,
2349ebfedea0SLionel Sambuc 	EVP_aes_256_cbc,
2350ebfedea0SLionel Sambuc 	CMSCBCParam_get,
2351ebfedea0SLionel Sambuc 	CMSCBCParam_set
2352ebfedea0SLionel Sambuc     }
2353ebfedea0SLionel Sambuc };
2354ebfedea0SLionel Sambuc 
2355ebfedea0SLionel Sambuc static const struct hx509cipher *
find_cipher_by_oid(const heim_oid * oid)2356ebfedea0SLionel Sambuc find_cipher_by_oid(const heim_oid *oid)
2357ebfedea0SLionel Sambuc {
2358*0a6a1f1dSLionel Sambuc     size_t i;
2359ebfedea0SLionel Sambuc 
2360ebfedea0SLionel Sambuc     for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
2361ebfedea0SLionel Sambuc 	if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0)
2362ebfedea0SLionel Sambuc 	    return &ciphers[i];
2363ebfedea0SLionel Sambuc 
2364ebfedea0SLionel Sambuc     return NULL;
2365ebfedea0SLionel Sambuc }
2366ebfedea0SLionel Sambuc 
2367ebfedea0SLionel Sambuc static const struct hx509cipher *
find_cipher_by_name(const char * name)2368ebfedea0SLionel Sambuc find_cipher_by_name(const char *name)
2369ebfedea0SLionel Sambuc {
2370*0a6a1f1dSLionel Sambuc     size_t i;
2371ebfedea0SLionel Sambuc 
2372ebfedea0SLionel Sambuc     for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
2373ebfedea0SLionel Sambuc 	if (strcasecmp(name, ciphers[i].name) == 0)
2374ebfedea0SLionel Sambuc 	    return &ciphers[i];
2375ebfedea0SLionel Sambuc 
2376ebfedea0SLionel Sambuc     return NULL;
2377ebfedea0SLionel Sambuc }
2378ebfedea0SLionel Sambuc 
2379ebfedea0SLionel Sambuc 
2380ebfedea0SLionel Sambuc const heim_oid *
hx509_crypto_enctype_by_name(const char * name)2381ebfedea0SLionel Sambuc hx509_crypto_enctype_by_name(const char *name)
2382ebfedea0SLionel Sambuc {
2383ebfedea0SLionel Sambuc     const struct hx509cipher *cipher;
2384ebfedea0SLionel Sambuc 
2385ebfedea0SLionel Sambuc     cipher = find_cipher_by_name(name);
2386ebfedea0SLionel Sambuc     if (cipher == NULL)
2387ebfedea0SLionel Sambuc 	return NULL;
2388ebfedea0SLionel Sambuc     return cipher->oid;
2389ebfedea0SLionel Sambuc }
2390ebfedea0SLionel Sambuc 
2391ebfedea0SLionel Sambuc int
hx509_crypto_init(hx509_context context,const char * provider,const heim_oid * enctype,hx509_crypto * crypto)2392ebfedea0SLionel Sambuc hx509_crypto_init(hx509_context context,
2393ebfedea0SLionel Sambuc 		  const char *provider,
2394ebfedea0SLionel Sambuc 		  const heim_oid *enctype,
2395ebfedea0SLionel Sambuc 		  hx509_crypto *crypto)
2396ebfedea0SLionel Sambuc {
2397ebfedea0SLionel Sambuc     const struct hx509cipher *cipher;
2398ebfedea0SLionel Sambuc 
2399ebfedea0SLionel Sambuc     *crypto = NULL;
2400ebfedea0SLionel Sambuc 
2401ebfedea0SLionel Sambuc     cipher = find_cipher_by_oid(enctype);
2402ebfedea0SLionel Sambuc     if (cipher == NULL) {
2403ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
2404ebfedea0SLionel Sambuc 			       "Algorithm not supported");
2405ebfedea0SLionel Sambuc 	return HX509_ALG_NOT_SUPP;
2406ebfedea0SLionel Sambuc     }
2407ebfedea0SLionel Sambuc 
2408ebfedea0SLionel Sambuc     *crypto = calloc(1, sizeof(**crypto));
2409ebfedea0SLionel Sambuc     if (*crypto == NULL) {
2410ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2411ebfedea0SLionel Sambuc 	return ENOMEM;
2412ebfedea0SLionel Sambuc     }
2413ebfedea0SLionel Sambuc 
2414ebfedea0SLionel Sambuc     (*crypto)->flags = PADDING_PKCS7;
2415ebfedea0SLionel Sambuc     (*crypto)->cipher = cipher;
2416ebfedea0SLionel Sambuc     (*crypto)->c = (*cipher->evp_func)();
2417ebfedea0SLionel Sambuc 
2418ebfedea0SLionel Sambuc     if (der_copy_oid(enctype, &(*crypto)->oid)) {
2419ebfedea0SLionel Sambuc 	hx509_crypto_destroy(*crypto);
2420ebfedea0SLionel Sambuc 	*crypto = NULL;
2421ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2422ebfedea0SLionel Sambuc 	return ENOMEM;
2423ebfedea0SLionel Sambuc     }
2424ebfedea0SLionel Sambuc 
2425ebfedea0SLionel Sambuc     return 0;
2426ebfedea0SLionel Sambuc }
2427ebfedea0SLionel Sambuc 
2428ebfedea0SLionel Sambuc const char *
hx509_crypto_provider(hx509_crypto crypto)2429ebfedea0SLionel Sambuc hx509_crypto_provider(hx509_crypto crypto)
2430ebfedea0SLionel Sambuc {
2431ebfedea0SLionel Sambuc     return "unknown";
2432ebfedea0SLionel Sambuc }
2433ebfedea0SLionel Sambuc 
2434ebfedea0SLionel Sambuc void
hx509_crypto_destroy(hx509_crypto crypto)2435ebfedea0SLionel Sambuc hx509_crypto_destroy(hx509_crypto crypto)
2436ebfedea0SLionel Sambuc {
2437ebfedea0SLionel Sambuc     if (crypto->name)
2438ebfedea0SLionel Sambuc 	free(crypto->name);
2439ebfedea0SLionel Sambuc     if (crypto->key.data)
2440ebfedea0SLionel Sambuc 	free(crypto->key.data);
2441ebfedea0SLionel Sambuc     if (crypto->param)
2442ebfedea0SLionel Sambuc 	free(crypto->param);
2443ebfedea0SLionel Sambuc     der_free_oid(&crypto->oid);
2444ebfedea0SLionel Sambuc     memset(crypto, 0, sizeof(*crypto));
2445ebfedea0SLionel Sambuc     free(crypto);
2446ebfedea0SLionel Sambuc }
2447ebfedea0SLionel Sambuc 
2448ebfedea0SLionel Sambuc int
hx509_crypto_set_key_name(hx509_crypto crypto,const char * name)2449ebfedea0SLionel Sambuc hx509_crypto_set_key_name(hx509_crypto crypto, const char *name)
2450ebfedea0SLionel Sambuc {
2451ebfedea0SLionel Sambuc     return 0;
2452ebfedea0SLionel Sambuc }
2453ebfedea0SLionel Sambuc 
2454ebfedea0SLionel Sambuc void
hx509_crypto_allow_weak(hx509_crypto crypto)2455ebfedea0SLionel Sambuc hx509_crypto_allow_weak(hx509_crypto crypto)
2456ebfedea0SLionel Sambuc {
2457ebfedea0SLionel Sambuc     crypto->flags |= ALLOW_WEAK;
2458ebfedea0SLionel Sambuc }
2459ebfedea0SLionel Sambuc 
2460ebfedea0SLionel Sambuc void
hx509_crypto_set_padding(hx509_crypto crypto,int padding_type)2461ebfedea0SLionel Sambuc hx509_crypto_set_padding(hx509_crypto crypto, int padding_type)
2462ebfedea0SLionel Sambuc {
2463ebfedea0SLionel Sambuc     switch (padding_type) {
2464ebfedea0SLionel Sambuc     case HX509_CRYPTO_PADDING_PKCS7:
2465ebfedea0SLionel Sambuc 	crypto->flags &= ~PADDING_FLAGS;
2466ebfedea0SLionel Sambuc 	crypto->flags |= PADDING_PKCS7;
2467ebfedea0SLionel Sambuc 	break;
2468ebfedea0SLionel Sambuc     case HX509_CRYPTO_PADDING_NONE:
2469ebfedea0SLionel Sambuc 	crypto->flags &= ~PADDING_FLAGS;
2470ebfedea0SLionel Sambuc 	crypto->flags |= PADDING_NONE;
2471ebfedea0SLionel Sambuc 	break;
2472ebfedea0SLionel Sambuc     default:
2473ebfedea0SLionel Sambuc 	_hx509_abort("Invalid padding");
2474ebfedea0SLionel Sambuc     }
2475ebfedea0SLionel Sambuc }
2476ebfedea0SLionel Sambuc 
2477ebfedea0SLionel Sambuc int
hx509_crypto_set_key_data(hx509_crypto crypto,const void * data,size_t length)2478ebfedea0SLionel Sambuc hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
2479ebfedea0SLionel Sambuc {
2480*0a6a1f1dSLionel Sambuc     if (EVP_CIPHER_key_length(crypto->c) > (int)length)
2481ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2482ebfedea0SLionel Sambuc 
2483ebfedea0SLionel Sambuc     if (crypto->key.data) {
2484ebfedea0SLionel Sambuc 	free(crypto->key.data);
2485ebfedea0SLionel Sambuc 	crypto->key.data = NULL;
2486ebfedea0SLionel Sambuc 	crypto->key.length = 0;
2487ebfedea0SLionel Sambuc     }
2488ebfedea0SLionel Sambuc     crypto->key.data = malloc(length);
2489ebfedea0SLionel Sambuc     if (crypto->key.data == NULL)
2490ebfedea0SLionel Sambuc 	return ENOMEM;
2491ebfedea0SLionel Sambuc     memcpy(crypto->key.data, data, length);
2492ebfedea0SLionel Sambuc     crypto->key.length = length;
2493ebfedea0SLionel Sambuc 
2494ebfedea0SLionel Sambuc     return 0;
2495ebfedea0SLionel Sambuc }
2496ebfedea0SLionel Sambuc 
2497ebfedea0SLionel Sambuc int
hx509_crypto_set_random_key(hx509_crypto crypto,heim_octet_string * key)2498ebfedea0SLionel Sambuc hx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key)
2499ebfedea0SLionel Sambuc {
2500ebfedea0SLionel Sambuc     if (crypto->key.data) {
2501ebfedea0SLionel Sambuc 	free(crypto->key.data);
2502ebfedea0SLionel Sambuc 	crypto->key.length = 0;
2503ebfedea0SLionel Sambuc     }
2504ebfedea0SLionel Sambuc 
2505ebfedea0SLionel Sambuc     crypto->key.length = EVP_CIPHER_key_length(crypto->c);
2506ebfedea0SLionel Sambuc     crypto->key.data = malloc(crypto->key.length);
2507ebfedea0SLionel Sambuc     if (crypto->key.data == NULL) {
2508ebfedea0SLionel Sambuc 	crypto->key.length = 0;
2509ebfedea0SLionel Sambuc 	return ENOMEM;
2510ebfedea0SLionel Sambuc     }
2511ebfedea0SLionel Sambuc     if (RAND_bytes(crypto->key.data, crypto->key.length) <= 0) {
2512ebfedea0SLionel Sambuc 	free(crypto->key.data);
2513ebfedea0SLionel Sambuc 	crypto->key.data = NULL;
2514ebfedea0SLionel Sambuc 	crypto->key.length = 0;
2515ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2516ebfedea0SLionel Sambuc     }
2517ebfedea0SLionel Sambuc     if (key)
2518ebfedea0SLionel Sambuc 	return der_copy_octet_string(&crypto->key, key);
2519ebfedea0SLionel Sambuc     else
2520ebfedea0SLionel Sambuc 	return 0;
2521ebfedea0SLionel Sambuc }
2522ebfedea0SLionel Sambuc 
2523ebfedea0SLionel Sambuc int
hx509_crypto_set_params(hx509_context context,hx509_crypto crypto,const heim_octet_string * param,heim_octet_string * ivec)2524ebfedea0SLionel Sambuc hx509_crypto_set_params(hx509_context context,
2525ebfedea0SLionel Sambuc 			hx509_crypto crypto,
2526ebfedea0SLionel Sambuc 			const heim_octet_string *param,
2527ebfedea0SLionel Sambuc 			heim_octet_string *ivec)
2528ebfedea0SLionel Sambuc {
2529ebfedea0SLionel Sambuc     return (*crypto->cipher->set_params)(context, param, crypto, ivec);
2530ebfedea0SLionel Sambuc }
2531ebfedea0SLionel Sambuc 
2532ebfedea0SLionel Sambuc int
hx509_crypto_get_params(hx509_context context,hx509_crypto crypto,const heim_octet_string * ivec,heim_octet_string * param)2533ebfedea0SLionel Sambuc hx509_crypto_get_params(hx509_context context,
2534ebfedea0SLionel Sambuc 			hx509_crypto crypto,
2535ebfedea0SLionel Sambuc 			const heim_octet_string *ivec,
2536ebfedea0SLionel Sambuc 			heim_octet_string *param)
2537ebfedea0SLionel Sambuc {
2538ebfedea0SLionel Sambuc     return (*crypto->cipher->get_params)(context, crypto, ivec, param);
2539ebfedea0SLionel Sambuc }
2540ebfedea0SLionel Sambuc 
2541ebfedea0SLionel Sambuc int
hx509_crypto_random_iv(hx509_crypto crypto,heim_octet_string * ivec)2542ebfedea0SLionel Sambuc hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
2543ebfedea0SLionel Sambuc {
2544ebfedea0SLionel Sambuc     ivec->length = EVP_CIPHER_iv_length(crypto->c);
2545ebfedea0SLionel Sambuc     ivec->data = malloc(ivec->length);
2546ebfedea0SLionel Sambuc     if (ivec->data == NULL) {
2547ebfedea0SLionel Sambuc 	ivec->length = 0;
2548ebfedea0SLionel Sambuc 	return ENOMEM;
2549ebfedea0SLionel Sambuc     }
2550ebfedea0SLionel Sambuc 
2551ebfedea0SLionel Sambuc     if (RAND_bytes(ivec->data, ivec->length) <= 0) {
2552ebfedea0SLionel Sambuc 	free(ivec->data);
2553ebfedea0SLionel Sambuc 	ivec->data = NULL;
2554ebfedea0SLionel Sambuc 	ivec->length = 0;
2555ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2556ebfedea0SLionel Sambuc     }
2557ebfedea0SLionel Sambuc     return 0;
2558ebfedea0SLionel Sambuc }
2559ebfedea0SLionel Sambuc 
2560ebfedea0SLionel Sambuc int
hx509_crypto_encrypt(hx509_crypto crypto,const void * data,const size_t length,const heim_octet_string * ivec,heim_octet_string ** ciphertext)2561ebfedea0SLionel Sambuc hx509_crypto_encrypt(hx509_crypto crypto,
2562ebfedea0SLionel Sambuc 		     const void *data,
2563ebfedea0SLionel Sambuc 		     const size_t length,
2564ebfedea0SLionel Sambuc 		     const heim_octet_string *ivec,
2565ebfedea0SLionel Sambuc 		     heim_octet_string **ciphertext)
2566ebfedea0SLionel Sambuc {
2567ebfedea0SLionel Sambuc     EVP_CIPHER_CTX evp;
2568ebfedea0SLionel Sambuc     size_t padsize, bsize;
2569ebfedea0SLionel Sambuc     int ret;
2570ebfedea0SLionel Sambuc 
2571ebfedea0SLionel Sambuc     *ciphertext = NULL;
2572ebfedea0SLionel Sambuc 
2573ebfedea0SLionel Sambuc     if ((crypto->cipher->flags & CIPHER_WEAK) &&
2574ebfedea0SLionel Sambuc 	(crypto->flags & ALLOW_WEAK) == 0)
2575ebfedea0SLionel Sambuc 	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
2576ebfedea0SLionel Sambuc 
2577*0a6a1f1dSLionel Sambuc     assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length);
2578ebfedea0SLionel Sambuc 
2579ebfedea0SLionel Sambuc     EVP_CIPHER_CTX_init(&evp);
2580ebfedea0SLionel Sambuc 
2581ebfedea0SLionel Sambuc     ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
2582ebfedea0SLionel Sambuc 			    crypto->key.data, ivec->data, 1);
2583ebfedea0SLionel Sambuc     if (ret != 1) {
2584ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&evp);
2585ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_INTERNAL_ERROR;
2586ebfedea0SLionel Sambuc 	goto out;
2587ebfedea0SLionel Sambuc     }
2588ebfedea0SLionel Sambuc 
2589ebfedea0SLionel Sambuc     *ciphertext = calloc(1, sizeof(**ciphertext));
2590ebfedea0SLionel Sambuc     if (*ciphertext == NULL) {
2591ebfedea0SLionel Sambuc 	ret = ENOMEM;
2592ebfedea0SLionel Sambuc 	goto out;
2593ebfedea0SLionel Sambuc     }
2594ebfedea0SLionel Sambuc 
2595ebfedea0SLionel Sambuc     assert(crypto->flags & PADDING_FLAGS);
2596ebfedea0SLionel Sambuc 
2597ebfedea0SLionel Sambuc     bsize = EVP_CIPHER_block_size(crypto->c);
2598ebfedea0SLionel Sambuc     padsize = 0;
2599ebfedea0SLionel Sambuc 
2600ebfedea0SLionel Sambuc     if (crypto->flags & PADDING_NONE) {
2601ebfedea0SLionel Sambuc 	if (bsize != 1 && (length % bsize) != 0)
2602ebfedea0SLionel Sambuc 	    return HX509_CMS_PADDING_ERROR;
2603ebfedea0SLionel Sambuc     } else if (crypto->flags & PADDING_PKCS7) {
2604ebfedea0SLionel Sambuc 	if (bsize != 1)
2605ebfedea0SLionel Sambuc 	    padsize = bsize - (length % bsize);
2606ebfedea0SLionel Sambuc     }
2607ebfedea0SLionel Sambuc 
2608ebfedea0SLionel Sambuc     (*ciphertext)->length = length + padsize;
2609ebfedea0SLionel Sambuc     (*ciphertext)->data = malloc(length + padsize);
2610ebfedea0SLionel Sambuc     if ((*ciphertext)->data == NULL) {
2611ebfedea0SLionel Sambuc 	ret = ENOMEM;
2612ebfedea0SLionel Sambuc 	goto out;
2613ebfedea0SLionel Sambuc     }
2614ebfedea0SLionel Sambuc 
2615ebfedea0SLionel Sambuc     memcpy((*ciphertext)->data, data, length);
2616ebfedea0SLionel Sambuc     if (padsize) {
2617*0a6a1f1dSLionel Sambuc 	size_t i;
2618ebfedea0SLionel Sambuc 	unsigned char *p = (*ciphertext)->data;
2619ebfedea0SLionel Sambuc 	p += length;
2620ebfedea0SLionel Sambuc 	for (i = 0; i < padsize; i++)
2621ebfedea0SLionel Sambuc 	    *p++ = padsize;
2622ebfedea0SLionel Sambuc     }
2623ebfedea0SLionel Sambuc 
2624ebfedea0SLionel Sambuc     ret = EVP_Cipher(&evp, (*ciphertext)->data,
2625ebfedea0SLionel Sambuc 		     (*ciphertext)->data,
2626ebfedea0SLionel Sambuc 		     length + padsize);
2627ebfedea0SLionel Sambuc     if (ret != 1) {
2628ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_INTERNAL_ERROR;
2629ebfedea0SLionel Sambuc 	goto out;
2630ebfedea0SLionel Sambuc     }
2631ebfedea0SLionel Sambuc     ret = 0;
2632ebfedea0SLionel Sambuc 
2633ebfedea0SLionel Sambuc  out:
2634ebfedea0SLionel Sambuc     if (ret) {
2635ebfedea0SLionel Sambuc 	if (*ciphertext) {
2636ebfedea0SLionel Sambuc 	    if ((*ciphertext)->data) {
2637ebfedea0SLionel Sambuc 		free((*ciphertext)->data);
2638ebfedea0SLionel Sambuc 	    }
2639ebfedea0SLionel Sambuc 	    free(*ciphertext);
2640ebfedea0SLionel Sambuc 	    *ciphertext = NULL;
2641ebfedea0SLionel Sambuc 	}
2642ebfedea0SLionel Sambuc     }
2643ebfedea0SLionel Sambuc     EVP_CIPHER_CTX_cleanup(&evp);
2644ebfedea0SLionel Sambuc 
2645ebfedea0SLionel Sambuc     return ret;
2646ebfedea0SLionel Sambuc }
2647ebfedea0SLionel Sambuc 
2648ebfedea0SLionel Sambuc int
hx509_crypto_decrypt(hx509_crypto crypto,const void * data,const size_t length,heim_octet_string * ivec,heim_octet_string * clear)2649ebfedea0SLionel Sambuc hx509_crypto_decrypt(hx509_crypto crypto,
2650ebfedea0SLionel Sambuc 		     const void *data,
2651ebfedea0SLionel Sambuc 		     const size_t length,
2652ebfedea0SLionel Sambuc 		     heim_octet_string *ivec,
2653ebfedea0SLionel Sambuc 		     heim_octet_string *clear)
2654ebfedea0SLionel Sambuc {
2655ebfedea0SLionel Sambuc     EVP_CIPHER_CTX evp;
2656ebfedea0SLionel Sambuc     void *idata = NULL;
2657ebfedea0SLionel Sambuc     int ret;
2658ebfedea0SLionel Sambuc 
2659ebfedea0SLionel Sambuc     clear->data = NULL;
2660ebfedea0SLionel Sambuc     clear->length = 0;
2661ebfedea0SLionel Sambuc 
2662ebfedea0SLionel Sambuc     if ((crypto->cipher->flags & CIPHER_WEAK) &&
2663ebfedea0SLionel Sambuc 	(crypto->flags & ALLOW_WEAK) == 0)
2664ebfedea0SLionel Sambuc 	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
2665ebfedea0SLionel Sambuc 
2666*0a6a1f1dSLionel Sambuc     if (ivec && EVP_CIPHER_iv_length(crypto->c) < (int)ivec->length)
2667ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2668ebfedea0SLionel Sambuc 
2669ebfedea0SLionel Sambuc     if (crypto->key.data == NULL)
2670ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2671ebfedea0SLionel Sambuc 
2672ebfedea0SLionel Sambuc     if (ivec)
2673ebfedea0SLionel Sambuc 	idata = ivec->data;
2674ebfedea0SLionel Sambuc 
2675ebfedea0SLionel Sambuc     EVP_CIPHER_CTX_init(&evp);
2676ebfedea0SLionel Sambuc 
2677ebfedea0SLionel Sambuc     ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
2678ebfedea0SLionel Sambuc 			    crypto->key.data, idata, 0);
2679ebfedea0SLionel Sambuc     if (ret != 1) {
2680ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&evp);
2681ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2682ebfedea0SLionel Sambuc     }
2683ebfedea0SLionel Sambuc 
2684ebfedea0SLionel Sambuc     clear->length = length;
2685ebfedea0SLionel Sambuc     clear->data = malloc(length);
2686ebfedea0SLionel Sambuc     if (clear->data == NULL) {
2687ebfedea0SLionel Sambuc 	EVP_CIPHER_CTX_cleanup(&evp);
2688ebfedea0SLionel Sambuc 	clear->length = 0;
2689ebfedea0SLionel Sambuc 	return ENOMEM;
2690ebfedea0SLionel Sambuc     }
2691ebfedea0SLionel Sambuc 
2692ebfedea0SLionel Sambuc     if (EVP_Cipher(&evp, clear->data, data, length) != 1) {
2693ebfedea0SLionel Sambuc 	return HX509_CRYPTO_INTERNAL_ERROR;
2694ebfedea0SLionel Sambuc     }
2695ebfedea0SLionel Sambuc     EVP_CIPHER_CTX_cleanup(&evp);
2696ebfedea0SLionel Sambuc 
2697ebfedea0SLionel Sambuc     if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) {
2698ebfedea0SLionel Sambuc 	int padsize;
2699ebfedea0SLionel Sambuc 	unsigned char *p;
2700ebfedea0SLionel Sambuc 	int j, bsize = EVP_CIPHER_block_size(crypto->c);
2701ebfedea0SLionel Sambuc 
2702*0a6a1f1dSLionel Sambuc 	if ((int)clear->length < bsize) {
2703ebfedea0SLionel Sambuc 	    ret = HX509_CMS_PADDING_ERROR;
2704ebfedea0SLionel Sambuc 	    goto out;
2705ebfedea0SLionel Sambuc 	}
2706ebfedea0SLionel Sambuc 
2707ebfedea0SLionel Sambuc 	p = clear->data;
2708ebfedea0SLionel Sambuc 	p += clear->length - 1;
2709ebfedea0SLionel Sambuc 	padsize = *p;
2710ebfedea0SLionel Sambuc 	if (padsize > bsize) {
2711ebfedea0SLionel Sambuc 	    ret = HX509_CMS_PADDING_ERROR;
2712ebfedea0SLionel Sambuc 	    goto out;
2713ebfedea0SLionel Sambuc 	}
2714ebfedea0SLionel Sambuc 	clear->length -= padsize;
2715ebfedea0SLionel Sambuc 	for (j = 0; j < padsize; j++) {
2716ebfedea0SLionel Sambuc 	    if (*p-- != padsize) {
2717ebfedea0SLionel Sambuc 		ret = HX509_CMS_PADDING_ERROR;
2718ebfedea0SLionel Sambuc 		goto out;
2719ebfedea0SLionel Sambuc 	    }
2720ebfedea0SLionel Sambuc 	}
2721ebfedea0SLionel Sambuc     }
2722ebfedea0SLionel Sambuc 
2723ebfedea0SLionel Sambuc     return 0;
2724ebfedea0SLionel Sambuc 
2725ebfedea0SLionel Sambuc  out:
2726ebfedea0SLionel Sambuc     if (clear->data)
2727ebfedea0SLionel Sambuc 	free(clear->data);
2728ebfedea0SLionel Sambuc     clear->data = NULL;
2729ebfedea0SLionel Sambuc     clear->length = 0;
2730ebfedea0SLionel Sambuc     return ret;
2731ebfedea0SLionel Sambuc }
2732ebfedea0SLionel Sambuc 
2733ebfedea0SLionel Sambuc typedef int (*PBE_string2key_func)(hx509_context,
2734ebfedea0SLionel Sambuc 				   const char *,
2735ebfedea0SLionel Sambuc 				   const heim_octet_string *,
2736ebfedea0SLionel Sambuc 				   hx509_crypto *, heim_octet_string *,
2737ebfedea0SLionel Sambuc 				   heim_octet_string *,
2738ebfedea0SLionel Sambuc 				   const heim_oid *, const EVP_MD *);
2739ebfedea0SLionel Sambuc 
2740ebfedea0SLionel Sambuc static int
PBE_string2key(hx509_context context,const char * password,const heim_octet_string * parameters,hx509_crypto * crypto,heim_octet_string * key,heim_octet_string * iv,const heim_oid * enc_oid,const EVP_MD * md)2741ebfedea0SLionel Sambuc PBE_string2key(hx509_context context,
2742ebfedea0SLionel Sambuc 	       const char *password,
2743ebfedea0SLionel Sambuc 	       const heim_octet_string *parameters,
2744ebfedea0SLionel Sambuc 	       hx509_crypto *crypto,
2745ebfedea0SLionel Sambuc 	       heim_octet_string *key, heim_octet_string *iv,
2746ebfedea0SLionel Sambuc 	       const heim_oid *enc_oid,
2747ebfedea0SLionel Sambuc 	       const EVP_MD *md)
2748ebfedea0SLionel Sambuc {
2749ebfedea0SLionel Sambuc     PKCS12_PBEParams p12params;
2750ebfedea0SLionel Sambuc     int passwordlen;
2751ebfedea0SLionel Sambuc     hx509_crypto c;
2752ebfedea0SLionel Sambuc     int iter, saltlen, ret;
2753ebfedea0SLionel Sambuc     unsigned char *salt;
2754ebfedea0SLionel Sambuc 
2755ebfedea0SLionel Sambuc     passwordlen = password ? strlen(password) : 0;
2756ebfedea0SLionel Sambuc 
2757ebfedea0SLionel Sambuc     if (parameters == NULL)
2758ebfedea0SLionel Sambuc  	return HX509_ALG_NOT_SUPP;
2759ebfedea0SLionel Sambuc 
2760ebfedea0SLionel Sambuc     ret = decode_PKCS12_PBEParams(parameters->data,
2761ebfedea0SLionel Sambuc 				  parameters->length,
2762ebfedea0SLionel Sambuc 				  &p12params, NULL);
2763ebfedea0SLionel Sambuc     if (ret)
2764ebfedea0SLionel Sambuc 	goto out;
2765ebfedea0SLionel Sambuc 
2766ebfedea0SLionel Sambuc     if (p12params.iterations)
2767ebfedea0SLionel Sambuc 	iter = *p12params.iterations;
2768ebfedea0SLionel Sambuc     else
2769ebfedea0SLionel Sambuc 	iter = 1;
2770ebfedea0SLionel Sambuc     salt = p12params.salt.data;
2771ebfedea0SLionel Sambuc     saltlen = p12params.salt.length;
2772ebfedea0SLionel Sambuc 
2773ebfedea0SLionel Sambuc     if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
2774ebfedea0SLionel Sambuc 			 PKCS12_KEY_ID, iter, key->length, key->data, md)) {
2775ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_INTERNAL_ERROR;
2776ebfedea0SLionel Sambuc 	goto out;
2777ebfedea0SLionel Sambuc     }
2778ebfedea0SLionel Sambuc 
2779ebfedea0SLionel Sambuc     if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
2780ebfedea0SLionel Sambuc 			 PKCS12_IV_ID, iter, iv->length, iv->data, md)) {
2781ebfedea0SLionel Sambuc 	ret = HX509_CRYPTO_INTERNAL_ERROR;
2782ebfedea0SLionel Sambuc 	goto out;
2783ebfedea0SLionel Sambuc     }
2784ebfedea0SLionel Sambuc 
2785ebfedea0SLionel Sambuc     ret = hx509_crypto_init(context, NULL, enc_oid, &c);
2786ebfedea0SLionel Sambuc     if (ret)
2787ebfedea0SLionel Sambuc 	goto out;
2788ebfedea0SLionel Sambuc 
2789ebfedea0SLionel Sambuc     hx509_crypto_allow_weak(c);
2790ebfedea0SLionel Sambuc 
2791ebfedea0SLionel Sambuc     ret = hx509_crypto_set_key_data(c, key->data, key->length);
2792ebfedea0SLionel Sambuc     if (ret) {
2793ebfedea0SLionel Sambuc 	hx509_crypto_destroy(c);
2794ebfedea0SLionel Sambuc 	goto out;
2795ebfedea0SLionel Sambuc     }
2796ebfedea0SLionel Sambuc 
2797ebfedea0SLionel Sambuc     *crypto = c;
2798ebfedea0SLionel Sambuc out:
2799ebfedea0SLionel Sambuc     free_PKCS12_PBEParams(&p12params);
2800ebfedea0SLionel Sambuc     return ret;
2801ebfedea0SLionel Sambuc }
2802ebfedea0SLionel Sambuc 
2803ebfedea0SLionel Sambuc static const heim_oid *
find_string2key(const heim_oid * oid,const EVP_CIPHER ** c,const EVP_MD ** md,PBE_string2key_func * s2k)2804ebfedea0SLionel Sambuc find_string2key(const heim_oid *oid,
2805ebfedea0SLionel Sambuc 		const EVP_CIPHER **c,
2806ebfedea0SLionel Sambuc 		const EVP_MD **md,
2807ebfedea0SLionel Sambuc 		PBE_string2key_func *s2k)
2808ebfedea0SLionel Sambuc {
2809ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) {
2810ebfedea0SLionel Sambuc 	*c = EVP_rc2_40_cbc();
2811ebfedea0SLionel Sambuc 	*md = EVP_sha1();
2812ebfedea0SLionel Sambuc 	*s2k = PBE_string2key;
2813ebfedea0SLionel Sambuc 	return &asn1_oid_private_rc2_40;
2814ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) {
2815ebfedea0SLionel Sambuc 	*c = EVP_rc2_cbc();
2816ebfedea0SLionel Sambuc 	*md = EVP_sha1();
2817ebfedea0SLionel Sambuc 	*s2k = PBE_string2key;
2818ebfedea0SLionel Sambuc 	return ASN1_OID_ID_PKCS3_RC2_CBC;
2819ebfedea0SLionel Sambuc #if 0
2820ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) {
2821ebfedea0SLionel Sambuc 	*c = EVP_rc4_40();
2822ebfedea0SLionel Sambuc 	*md = EVP_sha1();
2823ebfedea0SLionel Sambuc 	*s2k = PBE_string2key;
2824ebfedea0SLionel Sambuc 	return NULL;
2825ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) {
2826ebfedea0SLionel Sambuc 	*c = EVP_rc4();
2827ebfedea0SLionel Sambuc 	*md = EVP_sha1();
2828ebfedea0SLionel Sambuc 	*s2k = PBE_string2key;
2829ebfedea0SLionel Sambuc 	return ASN1_OID_ID_PKCS3_RC4;
2830ebfedea0SLionel Sambuc #endif
2831ebfedea0SLionel Sambuc     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) {
2832ebfedea0SLionel Sambuc 	*c = EVP_des_ede3_cbc();
2833ebfedea0SLionel Sambuc 	*md = EVP_sha1();
2834ebfedea0SLionel Sambuc 	*s2k = PBE_string2key;
2835ebfedea0SLionel Sambuc 	return ASN1_OID_ID_PKCS3_DES_EDE3_CBC;
2836ebfedea0SLionel Sambuc     }
2837ebfedea0SLionel Sambuc 
2838ebfedea0SLionel Sambuc     return NULL;
2839ebfedea0SLionel Sambuc }
2840ebfedea0SLionel Sambuc 
2841ebfedea0SLionel Sambuc /*
2842ebfedea0SLionel Sambuc  *
2843ebfedea0SLionel Sambuc  */
2844ebfedea0SLionel Sambuc 
2845ebfedea0SLionel Sambuc int
_hx509_pbe_encrypt(hx509_context context,hx509_lock lock,const AlgorithmIdentifier * ai,const heim_octet_string * content,heim_octet_string * econtent)2846ebfedea0SLionel Sambuc _hx509_pbe_encrypt(hx509_context context,
2847ebfedea0SLionel Sambuc 		   hx509_lock lock,
2848ebfedea0SLionel Sambuc 		   const AlgorithmIdentifier *ai,
2849ebfedea0SLionel Sambuc 		   const heim_octet_string *content,
2850ebfedea0SLionel Sambuc 		   heim_octet_string *econtent)
2851ebfedea0SLionel Sambuc {
2852ebfedea0SLionel Sambuc     hx509_clear_error_string(context);
2853ebfedea0SLionel Sambuc     return EINVAL;
2854ebfedea0SLionel Sambuc }
2855ebfedea0SLionel Sambuc 
2856ebfedea0SLionel Sambuc /*
2857ebfedea0SLionel Sambuc  *
2858ebfedea0SLionel Sambuc  */
2859ebfedea0SLionel Sambuc 
2860ebfedea0SLionel Sambuc int
_hx509_pbe_decrypt(hx509_context context,hx509_lock lock,const AlgorithmIdentifier * ai,const heim_octet_string * econtent,heim_octet_string * content)2861ebfedea0SLionel Sambuc _hx509_pbe_decrypt(hx509_context context,
2862ebfedea0SLionel Sambuc 		   hx509_lock lock,
2863ebfedea0SLionel Sambuc 		   const AlgorithmIdentifier *ai,
2864ebfedea0SLionel Sambuc 		   const heim_octet_string *econtent,
2865ebfedea0SLionel Sambuc 		   heim_octet_string *content)
2866ebfedea0SLionel Sambuc {
2867ebfedea0SLionel Sambuc     const struct _hx509_password *pw;
2868ebfedea0SLionel Sambuc     heim_octet_string key, iv;
2869ebfedea0SLionel Sambuc     const heim_oid *enc_oid;
2870ebfedea0SLionel Sambuc     const EVP_CIPHER *c;
2871ebfedea0SLionel Sambuc     const EVP_MD *md;
2872ebfedea0SLionel Sambuc     PBE_string2key_func s2k;
2873*0a6a1f1dSLionel Sambuc     int ret = 0;
2874*0a6a1f1dSLionel Sambuc     size_t i;
2875ebfedea0SLionel Sambuc 
2876ebfedea0SLionel Sambuc     memset(&key, 0, sizeof(key));
2877ebfedea0SLionel Sambuc     memset(&iv, 0, sizeof(iv));
2878ebfedea0SLionel Sambuc 
2879ebfedea0SLionel Sambuc     memset(content, 0, sizeof(*content));
2880ebfedea0SLionel Sambuc 
2881ebfedea0SLionel Sambuc     enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k);
2882ebfedea0SLionel Sambuc     if (enc_oid == NULL) {
2883ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
2884ebfedea0SLionel Sambuc 			       "String to key algorithm not supported");
2885ebfedea0SLionel Sambuc 	ret = HX509_ALG_NOT_SUPP;
2886ebfedea0SLionel Sambuc 	goto out;
2887ebfedea0SLionel Sambuc     }
2888ebfedea0SLionel Sambuc 
2889ebfedea0SLionel Sambuc     key.length = EVP_CIPHER_key_length(c);
2890ebfedea0SLionel Sambuc     key.data = malloc(key.length);
2891ebfedea0SLionel Sambuc     if (key.data == NULL) {
2892ebfedea0SLionel Sambuc 	ret = ENOMEM;
2893ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2894ebfedea0SLionel Sambuc 	goto out;
2895ebfedea0SLionel Sambuc     }
2896ebfedea0SLionel Sambuc 
2897ebfedea0SLionel Sambuc     iv.length = EVP_CIPHER_iv_length(c);
2898ebfedea0SLionel Sambuc     iv.data = malloc(iv.length);
2899ebfedea0SLionel Sambuc     if (iv.data == NULL) {
2900ebfedea0SLionel Sambuc 	ret = ENOMEM;
2901ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
2902ebfedea0SLionel Sambuc 	goto out;
2903ebfedea0SLionel Sambuc     }
2904ebfedea0SLionel Sambuc 
2905ebfedea0SLionel Sambuc     pw = _hx509_lock_get_passwords(lock);
2906ebfedea0SLionel Sambuc 
2907ebfedea0SLionel Sambuc     ret = HX509_CRYPTO_INTERNAL_ERROR;
2908ebfedea0SLionel Sambuc     for (i = 0; i < pw->len + 1; i++) {
2909ebfedea0SLionel Sambuc 	hx509_crypto crypto;
2910ebfedea0SLionel Sambuc 	const char *password;
2911ebfedea0SLionel Sambuc 
2912ebfedea0SLionel Sambuc 	if (i < pw->len)
2913ebfedea0SLionel Sambuc 	    password = pw->val[i];
2914ebfedea0SLionel Sambuc 	else if (i < pw->len + 1)
2915ebfedea0SLionel Sambuc 	    password = "";
2916ebfedea0SLionel Sambuc 	else
2917ebfedea0SLionel Sambuc 	    password = NULL;
2918ebfedea0SLionel Sambuc 
2919ebfedea0SLionel Sambuc 	ret = (*s2k)(context, password, ai->parameters, &crypto,
2920ebfedea0SLionel Sambuc 		     &key, &iv, enc_oid, md);
2921ebfedea0SLionel Sambuc 	if (ret)
2922ebfedea0SLionel Sambuc 	    goto out;
2923ebfedea0SLionel Sambuc 
2924ebfedea0SLionel Sambuc 	ret = hx509_crypto_decrypt(crypto,
2925ebfedea0SLionel Sambuc 				   econtent->data,
2926ebfedea0SLionel Sambuc 				   econtent->length,
2927ebfedea0SLionel Sambuc 				   &iv,
2928ebfedea0SLionel Sambuc 				   content);
2929ebfedea0SLionel Sambuc 	hx509_crypto_destroy(crypto);
2930ebfedea0SLionel Sambuc 	if (ret == 0)
2931ebfedea0SLionel Sambuc 	    goto out;
2932ebfedea0SLionel Sambuc 
2933ebfedea0SLionel Sambuc     }
2934ebfedea0SLionel Sambuc out:
2935ebfedea0SLionel Sambuc     if (key.data)
2936ebfedea0SLionel Sambuc 	der_free_octet_string(&key);
2937ebfedea0SLionel Sambuc     if (iv.data)
2938ebfedea0SLionel Sambuc 	der_free_octet_string(&iv);
2939ebfedea0SLionel Sambuc     return ret;
2940ebfedea0SLionel Sambuc }
2941ebfedea0SLionel Sambuc 
2942ebfedea0SLionel Sambuc /*
2943ebfedea0SLionel Sambuc  *
2944ebfedea0SLionel Sambuc  */
2945ebfedea0SLionel Sambuc 
2946ebfedea0SLionel Sambuc 
2947ebfedea0SLionel Sambuc static int
match_keys_rsa(hx509_cert c,hx509_private_key private_key)2948ebfedea0SLionel Sambuc match_keys_rsa(hx509_cert c, hx509_private_key private_key)
2949ebfedea0SLionel Sambuc {
2950ebfedea0SLionel Sambuc     const Certificate *cert;
2951ebfedea0SLionel Sambuc     const SubjectPublicKeyInfo *spi;
2952ebfedea0SLionel Sambuc     RSAPublicKey pk;
2953ebfedea0SLionel Sambuc     RSA *rsa;
2954ebfedea0SLionel Sambuc     size_t size;
2955ebfedea0SLionel Sambuc     int ret;
2956ebfedea0SLionel Sambuc 
2957ebfedea0SLionel Sambuc     if (private_key->private_key.rsa == NULL)
2958ebfedea0SLionel Sambuc 	return 0;
2959ebfedea0SLionel Sambuc 
2960ebfedea0SLionel Sambuc     rsa = private_key->private_key.rsa;
2961ebfedea0SLionel Sambuc     if (rsa->d == NULL || rsa->p == NULL || rsa->q == NULL)
2962ebfedea0SLionel Sambuc 	return 0;
2963ebfedea0SLionel Sambuc 
2964ebfedea0SLionel Sambuc     cert = _hx509_get_cert(c);
2965ebfedea0SLionel Sambuc     spi = &cert->tbsCertificate.subjectPublicKeyInfo;
2966ebfedea0SLionel Sambuc 
2967ebfedea0SLionel Sambuc     rsa = RSA_new();
2968ebfedea0SLionel Sambuc     if (rsa == NULL)
2969ebfedea0SLionel Sambuc 	return 0;
2970ebfedea0SLionel Sambuc 
2971ebfedea0SLionel Sambuc     ret = decode_RSAPublicKey(spi->subjectPublicKey.data,
2972ebfedea0SLionel Sambuc 			      spi->subjectPublicKey.length / 8,
2973ebfedea0SLionel Sambuc 			      &pk, &size);
2974ebfedea0SLionel Sambuc     if (ret) {
2975ebfedea0SLionel Sambuc 	RSA_free(rsa);
2976ebfedea0SLionel Sambuc 	return 0;
2977ebfedea0SLionel Sambuc     }
2978ebfedea0SLionel Sambuc     rsa->n = heim_int2BN(&pk.modulus);
2979ebfedea0SLionel Sambuc     rsa->e = heim_int2BN(&pk.publicExponent);
2980ebfedea0SLionel Sambuc 
2981ebfedea0SLionel Sambuc     free_RSAPublicKey(&pk);
2982ebfedea0SLionel Sambuc 
2983ebfedea0SLionel Sambuc     rsa->d = BN_dup(private_key->private_key.rsa->d);
2984ebfedea0SLionel Sambuc     rsa->p = BN_dup(private_key->private_key.rsa->p);
2985ebfedea0SLionel Sambuc     rsa->q = BN_dup(private_key->private_key.rsa->q);
2986ebfedea0SLionel Sambuc     rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
2987ebfedea0SLionel Sambuc     rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1);
2988ebfedea0SLionel Sambuc     rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp);
2989ebfedea0SLionel Sambuc 
2990ebfedea0SLionel Sambuc     if (rsa->n == NULL || rsa->e == NULL ||
2991ebfedea0SLionel Sambuc 	rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||
2992ebfedea0SLionel Sambuc 	rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
2993ebfedea0SLionel Sambuc 	RSA_free(rsa);
2994ebfedea0SLionel Sambuc 	return 0;
2995ebfedea0SLionel Sambuc     }
2996ebfedea0SLionel Sambuc 
2997ebfedea0SLionel Sambuc     ret = RSA_check_key(rsa);
2998ebfedea0SLionel Sambuc     RSA_free(rsa);
2999ebfedea0SLionel Sambuc 
3000ebfedea0SLionel Sambuc     return ret == 1;
3001ebfedea0SLionel Sambuc }
3002ebfedea0SLionel Sambuc 
3003ebfedea0SLionel Sambuc static int
match_keys_ec(hx509_cert c,hx509_private_key private_key)3004ebfedea0SLionel Sambuc match_keys_ec(hx509_cert c, hx509_private_key private_key)
3005ebfedea0SLionel Sambuc {
3006ebfedea0SLionel Sambuc     return 1; /* XXX use EC_KEY_check_key */
3007ebfedea0SLionel Sambuc }
3008ebfedea0SLionel Sambuc 
3009ebfedea0SLionel Sambuc 
3010ebfedea0SLionel Sambuc int
_hx509_match_keys(hx509_cert c,hx509_private_key key)3011ebfedea0SLionel Sambuc _hx509_match_keys(hx509_cert c, hx509_private_key key)
3012ebfedea0SLionel Sambuc {
3013ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0)
3014ebfedea0SLionel Sambuc 	return match_keys_rsa(c, key);
3015ebfedea0SLionel Sambuc     if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0)
3016ebfedea0SLionel Sambuc 	return match_keys_ec(c, key);
3017ebfedea0SLionel Sambuc     return 0;
3018ebfedea0SLionel Sambuc 
3019ebfedea0SLionel Sambuc }
3020ebfedea0SLionel Sambuc 
3021ebfedea0SLionel Sambuc 
3022ebfedea0SLionel Sambuc static const heim_oid *
find_keytype(const hx509_private_key key)3023ebfedea0SLionel Sambuc find_keytype(const hx509_private_key key)
3024ebfedea0SLionel Sambuc {
3025ebfedea0SLionel Sambuc     const struct signature_alg *md;
3026ebfedea0SLionel Sambuc 
3027ebfedea0SLionel Sambuc     if (key == NULL)
3028ebfedea0SLionel Sambuc 	return NULL;
3029ebfedea0SLionel Sambuc 
3030ebfedea0SLionel Sambuc     md = find_sig_alg(key->signature_alg);
3031ebfedea0SLionel Sambuc     if (md == NULL)
3032ebfedea0SLionel Sambuc 	return NULL;
3033ebfedea0SLionel Sambuc     return md->key_oid;
3034ebfedea0SLionel Sambuc }
3035ebfedea0SLionel Sambuc 
3036ebfedea0SLionel Sambuc int
hx509_crypto_select(const hx509_context context,int type,const hx509_private_key source,hx509_peer_info peer,AlgorithmIdentifier * selected)3037ebfedea0SLionel Sambuc hx509_crypto_select(const hx509_context context,
3038ebfedea0SLionel Sambuc 		    int type,
3039ebfedea0SLionel Sambuc 		    const hx509_private_key source,
3040ebfedea0SLionel Sambuc 		    hx509_peer_info peer,
3041ebfedea0SLionel Sambuc 		    AlgorithmIdentifier *selected)
3042ebfedea0SLionel Sambuc {
3043ebfedea0SLionel Sambuc     const AlgorithmIdentifier *def = NULL;
3044ebfedea0SLionel Sambuc     size_t i, j;
3045ebfedea0SLionel Sambuc     int ret, bits;
3046ebfedea0SLionel Sambuc 
3047ebfedea0SLionel Sambuc     memset(selected, 0, sizeof(*selected));
3048ebfedea0SLionel Sambuc 
3049ebfedea0SLionel Sambuc     if (type == HX509_SELECT_DIGEST) {
3050ebfedea0SLionel Sambuc 	bits = SIG_DIGEST;
3051ebfedea0SLionel Sambuc 	if (source)
3052ebfedea0SLionel Sambuc 	    def = alg_for_privatekey(source, type);
3053ebfedea0SLionel Sambuc 	if (def == NULL)
3054ebfedea0SLionel Sambuc 	    def = _hx509_crypto_default_digest_alg;
3055ebfedea0SLionel Sambuc     } else if (type == HX509_SELECT_PUBLIC_SIG) {
3056ebfedea0SLionel Sambuc 	bits = SIG_PUBLIC_SIG;
3057ebfedea0SLionel Sambuc 	/* XXX depend on `source´ and `peer´ */
3058ebfedea0SLionel Sambuc 	if (source)
3059ebfedea0SLionel Sambuc 	    def = alg_for_privatekey(source, type);
3060ebfedea0SLionel Sambuc 	if (def == NULL)
3061ebfedea0SLionel Sambuc 	    def = _hx509_crypto_default_sig_alg;
3062ebfedea0SLionel Sambuc     } else if (type == HX509_SELECT_SECRET_ENC) {
3063ebfedea0SLionel Sambuc 	bits = SIG_SECRET;
3064ebfedea0SLionel Sambuc 	def = _hx509_crypto_default_secret_alg;
3065ebfedea0SLionel Sambuc     } else {
3066ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, EINVAL,
3067ebfedea0SLionel Sambuc 			       "Unknown type %d of selection", type);
3068ebfedea0SLionel Sambuc 	return EINVAL;
3069ebfedea0SLionel Sambuc     }
3070ebfedea0SLionel Sambuc 
3071ebfedea0SLionel Sambuc     if (peer) {
3072ebfedea0SLionel Sambuc 	const heim_oid *keytype = NULL;
3073ebfedea0SLionel Sambuc 
3074ebfedea0SLionel Sambuc 	keytype = find_keytype(source);
3075ebfedea0SLionel Sambuc 
3076ebfedea0SLionel Sambuc 	for (i = 0; i < peer->len; i++) {
3077ebfedea0SLionel Sambuc 	    for (j = 0; sig_algs[j]; j++) {
3078ebfedea0SLionel Sambuc 		if ((sig_algs[j]->flags & bits) != bits)
3079ebfedea0SLionel Sambuc 		    continue;
3080ebfedea0SLionel Sambuc 		if (der_heim_oid_cmp(sig_algs[j]->sig_oid,
3081ebfedea0SLionel Sambuc 				     &peer->val[i].algorithm) != 0)
3082ebfedea0SLionel Sambuc 		    continue;
3083ebfedea0SLionel Sambuc 		if (keytype && sig_algs[j]->key_oid &&
3084ebfedea0SLionel Sambuc 		    der_heim_oid_cmp(keytype, sig_algs[j]->key_oid))
3085ebfedea0SLionel Sambuc 		    continue;
3086ebfedea0SLionel Sambuc 
3087ebfedea0SLionel Sambuc 		/* found one, use that */
3088ebfedea0SLionel Sambuc 		ret = copy_AlgorithmIdentifier(&peer->val[i], selected);
3089ebfedea0SLionel Sambuc 		if (ret)
3090ebfedea0SLionel Sambuc 		    hx509_clear_error_string(context);
3091ebfedea0SLionel Sambuc 		return ret;
3092ebfedea0SLionel Sambuc 	    }
3093ebfedea0SLionel Sambuc 	    if (bits & SIG_SECRET) {
3094ebfedea0SLionel Sambuc 		const struct hx509cipher *cipher;
3095ebfedea0SLionel Sambuc 
3096ebfedea0SLionel Sambuc 		cipher = find_cipher_by_oid(&peer->val[i].algorithm);
3097ebfedea0SLionel Sambuc 		if (cipher == NULL)
3098ebfedea0SLionel Sambuc 		    continue;
3099ebfedea0SLionel Sambuc 		if (cipher->ai_func == NULL)
3100ebfedea0SLionel Sambuc 		    continue;
3101ebfedea0SLionel Sambuc 		ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected);
3102ebfedea0SLionel Sambuc 		if (ret)
3103ebfedea0SLionel Sambuc 		    hx509_clear_error_string(context);
3104ebfedea0SLionel Sambuc 		return ret;
3105ebfedea0SLionel Sambuc 	    }
3106ebfedea0SLionel Sambuc 	}
3107ebfedea0SLionel Sambuc     }
3108ebfedea0SLionel Sambuc 
3109ebfedea0SLionel Sambuc     /* use default */
3110ebfedea0SLionel Sambuc     ret = copy_AlgorithmIdentifier(def, selected);
3111ebfedea0SLionel Sambuc     if (ret)
3112ebfedea0SLionel Sambuc 	hx509_clear_error_string(context);
3113ebfedea0SLionel Sambuc     return ret;
3114ebfedea0SLionel Sambuc }
3115ebfedea0SLionel Sambuc 
3116ebfedea0SLionel Sambuc int
hx509_crypto_available(hx509_context context,int type,hx509_cert source,AlgorithmIdentifier ** val,unsigned int * plen)3117ebfedea0SLionel Sambuc hx509_crypto_available(hx509_context context,
3118ebfedea0SLionel Sambuc 		       int type,
3119ebfedea0SLionel Sambuc 		       hx509_cert source,
3120ebfedea0SLionel Sambuc 		       AlgorithmIdentifier **val,
3121ebfedea0SLionel Sambuc 		       unsigned int *plen)
3122ebfedea0SLionel Sambuc {
3123ebfedea0SLionel Sambuc     const heim_oid *keytype = NULL;
3124ebfedea0SLionel Sambuc     unsigned int len, i;
3125ebfedea0SLionel Sambuc     void *ptr;
3126ebfedea0SLionel Sambuc     int bits, ret;
3127ebfedea0SLionel Sambuc 
3128ebfedea0SLionel Sambuc     *val = NULL;
3129ebfedea0SLionel Sambuc 
3130ebfedea0SLionel Sambuc     if (type == HX509_SELECT_ALL) {
3131ebfedea0SLionel Sambuc 	bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET;
3132ebfedea0SLionel Sambuc     } else if (type == HX509_SELECT_DIGEST) {
3133ebfedea0SLionel Sambuc 	bits = SIG_DIGEST;
3134ebfedea0SLionel Sambuc     } else if (type == HX509_SELECT_PUBLIC_SIG) {
3135ebfedea0SLionel Sambuc 	bits = SIG_PUBLIC_SIG;
3136ebfedea0SLionel Sambuc     } else {
3137ebfedea0SLionel Sambuc 	hx509_set_error_string(context, 0, EINVAL,
3138ebfedea0SLionel Sambuc 			       "Unknown type %d of available", type);
3139ebfedea0SLionel Sambuc 	return EINVAL;
3140ebfedea0SLionel Sambuc     }
3141ebfedea0SLionel Sambuc 
3142ebfedea0SLionel Sambuc     if (source)
3143ebfedea0SLionel Sambuc 	keytype = find_keytype(_hx509_cert_private_key(source));
3144ebfedea0SLionel Sambuc 
3145ebfedea0SLionel Sambuc     len = 0;
3146ebfedea0SLionel Sambuc     for (i = 0; sig_algs[i]; i++) {
3147ebfedea0SLionel Sambuc 	if ((sig_algs[i]->flags & bits) == 0)
3148ebfedea0SLionel Sambuc 	    continue;
3149ebfedea0SLionel Sambuc 	if (sig_algs[i]->sig_alg == NULL)
3150ebfedea0SLionel Sambuc 	    continue;
3151ebfedea0SLionel Sambuc 	if (keytype && sig_algs[i]->key_oid &&
3152ebfedea0SLionel Sambuc 	    der_heim_oid_cmp(sig_algs[i]->key_oid, keytype))
3153ebfedea0SLionel Sambuc 	    continue;
3154ebfedea0SLionel Sambuc 
3155ebfedea0SLionel Sambuc 	/* found one, add that to the list */
3156ebfedea0SLionel Sambuc 	ptr = realloc(*val, sizeof(**val) * (len + 1));
3157ebfedea0SLionel Sambuc 	if (ptr == NULL)
3158ebfedea0SLionel Sambuc 	    goto out;
3159ebfedea0SLionel Sambuc 	*val = ptr;
3160ebfedea0SLionel Sambuc 
3161ebfedea0SLionel Sambuc 	ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]);
3162ebfedea0SLionel Sambuc 	if (ret)
3163ebfedea0SLionel Sambuc 	    goto out;
3164ebfedea0SLionel Sambuc 	len++;
3165ebfedea0SLionel Sambuc     }
3166ebfedea0SLionel Sambuc 
3167ebfedea0SLionel Sambuc     /* Add AES */
3168ebfedea0SLionel Sambuc     if (bits & SIG_SECRET) {
3169ebfedea0SLionel Sambuc 
3170ebfedea0SLionel Sambuc 	for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
3171ebfedea0SLionel Sambuc 
3172ebfedea0SLionel Sambuc 	    if (ciphers[i].flags & CIPHER_WEAK)
3173ebfedea0SLionel Sambuc 		continue;
3174ebfedea0SLionel Sambuc 	    if (ciphers[i].ai_func == NULL)
3175ebfedea0SLionel Sambuc 		continue;
3176ebfedea0SLionel Sambuc 
3177ebfedea0SLionel Sambuc 	    ptr = realloc(*val, sizeof(**val) * (len + 1));
3178ebfedea0SLionel Sambuc 	    if (ptr == NULL)
3179ebfedea0SLionel Sambuc 		goto out;
3180ebfedea0SLionel Sambuc 	    *val = ptr;
3181ebfedea0SLionel Sambuc 
3182ebfedea0SLionel Sambuc 	    ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]);
3183ebfedea0SLionel Sambuc 	    if (ret)
3184ebfedea0SLionel Sambuc 		goto out;
3185ebfedea0SLionel Sambuc 	    len++;
3186ebfedea0SLionel Sambuc 	}
3187ebfedea0SLionel Sambuc     }
3188ebfedea0SLionel Sambuc 
3189ebfedea0SLionel Sambuc     *plen = len;
3190ebfedea0SLionel Sambuc     return 0;
3191ebfedea0SLionel Sambuc 
3192ebfedea0SLionel Sambuc out:
3193ebfedea0SLionel Sambuc     for (i = 0; i < len; i++)
3194ebfedea0SLionel Sambuc 	free_AlgorithmIdentifier(&(*val)[i]);
3195ebfedea0SLionel Sambuc     free(*val);
3196ebfedea0SLionel Sambuc     *val = NULL;
3197ebfedea0SLionel Sambuc     hx509_set_error_string(context, 0, ENOMEM, "out of memory");
3198ebfedea0SLionel Sambuc     return ENOMEM;
3199ebfedea0SLionel Sambuc }
3200ebfedea0SLionel Sambuc 
3201ebfedea0SLionel Sambuc void
hx509_crypto_free_algs(AlgorithmIdentifier * val,unsigned int len)3202ebfedea0SLionel Sambuc hx509_crypto_free_algs(AlgorithmIdentifier *val,
3203ebfedea0SLionel Sambuc 		       unsigned int len)
3204ebfedea0SLionel Sambuc {
3205ebfedea0SLionel Sambuc     unsigned int i;
3206ebfedea0SLionel Sambuc     for (i = 0; i < len; i++)
3207ebfedea0SLionel Sambuc 	free_AlgorithmIdentifier(&val[i]);
3208ebfedea0SLionel Sambuc     free(val);
3209ebfedea0SLionel Sambuc }
3210