1178825Sdfr/*
2233294Sstas * Copyright (c) 2004 - 2007 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#include "hx_locl.h"
35178825Sdfr
36178825Sdfrstruct hx509_crypto;
37178825Sdfr
38178825Sdfrstruct signature_alg;
39178825Sdfr
40178825Sdfrstruct hx509_generate_private_context {
41178825Sdfr    const heim_oid *key_oid;
42178825Sdfr    int isCA;
43178825Sdfr    unsigned long num_bits;
44178825Sdfr};
45178825Sdfr
46178825Sdfrstruct hx509_private_key_ops {
47178825Sdfr    const char *pemtype;
48233294Sstas    const heim_oid *key_oid;
49233294Sstas    int (*available)(const hx509_private_key,
50233294Sstas		     const AlgorithmIdentifier *);
51178825Sdfr    int (*get_spki)(hx509_context,
52178825Sdfr		    const hx509_private_key,
53178825Sdfr		    SubjectPublicKeyInfo *);
54178825Sdfr    int (*export)(hx509_context context,
55178825Sdfr		  const hx509_private_key,
56233294Sstas		  hx509_key_format_t,
57178825Sdfr		  heim_octet_string *);
58233294Sstas    int (*import)(hx509_context, const AlgorithmIdentifier *,
59233294Sstas		  const void *, size_t, hx509_key_format_t,
60233294Sstas		  hx509_private_key);
61178825Sdfr    int (*generate_private_key)(hx509_context,
62178825Sdfr				struct hx509_generate_private_context *,
63178825Sdfr				hx509_private_key);
64178825Sdfr    BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);
65178825Sdfr};
66178825Sdfr
67178825Sdfrstruct hx509_private_key {
68178825Sdfr    unsigned int ref;
69178825Sdfr    const struct signature_alg *md;
70178825Sdfr    const heim_oid *signature_alg;
71178825Sdfr    union {
72178825Sdfr	RSA *rsa;
73178825Sdfr	void *keydata;
74233294Sstas#ifdef HAVE_OPENSSL
75233294Sstas	EC_KEY *ecdsa;
76233294Sstas#endif
77178825Sdfr    } private_key;
78178825Sdfr    hx509_private_key_ops *ops;
79178825Sdfr};
80178825Sdfr
81178825Sdfr/*
82178825Sdfr *
83178825Sdfr */
84178825Sdfr
85178825Sdfrstruct signature_alg {
86178825Sdfr    const char *name;
87233294Sstas    const heim_oid *sig_oid;
88233294Sstas    const AlgorithmIdentifier *sig_alg;
89233294Sstas    const heim_oid *key_oid;
90233294Sstas    const AlgorithmIdentifier *digest_alg;
91178825Sdfr    int flags;
92233294Sstas#define PROVIDE_CONF	0x1
93233294Sstas#define REQUIRE_SIGNER	0x2
94233294Sstas#define SELF_SIGNED_OK	0x4
95178825Sdfr
96178825Sdfr#define SIG_DIGEST	0x100
97178825Sdfr#define SIG_PUBLIC_SIG	0x200
98178825Sdfr#define SIG_SECRET	0x400
99178825Sdfr
100178825Sdfr#define RA_RSA_USES_DIGEST_INFO 0x1000000
101178825Sdfr
102233294Sstas    time_t best_before; /* refuse signature made after best before date */
103233294Sstas    const EVP_MD *(*evp_md)(void);
104178825Sdfr    int (*verify_signature)(hx509_context context,
105178825Sdfr			    const struct signature_alg *,
106178825Sdfr			    const Certificate *,
107178825Sdfr			    const AlgorithmIdentifier *,
108178825Sdfr			    const heim_octet_string *,
109178825Sdfr			    const heim_octet_string *);
110178825Sdfr    int (*create_signature)(hx509_context,
111178825Sdfr			    const struct signature_alg *,
112178825Sdfr			    const hx509_private_key,
113178825Sdfr			    const AlgorithmIdentifier *,
114178825Sdfr			    const heim_octet_string *,
115178825Sdfr			    AlgorithmIdentifier *,
116178825Sdfr			    heim_octet_string *);
117233294Sstas    int digest_size;
118178825Sdfr};
119178825Sdfr
120233294Sstasstatic const struct signature_alg *
121233294Sstasfind_sig_alg(const heim_oid *oid);
122233294Sstas
123178825Sdfr/*
124178825Sdfr *
125178825Sdfr */
126178825Sdfr
127233294Sstasstatic const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
128233294Sstas
129233294Sstasstatic const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
130233294Sstasconst AlgorithmIdentifier _hx509_signature_sha512_data = {
131233294Sstas    { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
132233294Sstas};
133233294Sstas
134233294Sstasstatic const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
135233294Sstasconst AlgorithmIdentifier _hx509_signature_sha384_data = {
136233294Sstas    { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
137233294Sstas};
138233294Sstas
139233294Sstasstatic const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
140233294Sstasconst AlgorithmIdentifier _hx509_signature_sha256_data = {
141233294Sstas    { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
142233294Sstas};
143233294Sstas
144233294Sstasstatic const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
145233294Sstasconst AlgorithmIdentifier _hx509_signature_sha1_data = {
146233294Sstas    { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
147233294Sstas};
148233294Sstas
149233294Sstasstatic const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
150233294Sstasconst AlgorithmIdentifier _hx509_signature_md5_data = {
151233294Sstas    { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
152233294Sstas};
153233294Sstas
154233294Sstasstatic const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
155233294Sstasconst AlgorithmIdentifier _hx509_signature_ecPublicKey = {
156233294Sstas    { 6, rk_UNCONST(ecPublicKey) }, NULL
157233294Sstas};
158233294Sstas
159233294Sstasstatic const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
160233294Sstasconst AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
161233294Sstas    { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
162233294Sstas};
163233294Sstas
164233294Sstasstatic const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
165233294Sstasconst AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
166233294Sstas    { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
167233294Sstas};
168233294Sstas
169233294Sstasstatic const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
170233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
171233294Sstas    { 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL
172233294Sstas};
173233294Sstas
174233294Sstasstatic const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
175233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
176233294Sstas    { 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL
177233294Sstas};
178233294Sstas
179233294Sstasstatic const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
180233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
181233294Sstas    { 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL
182233294Sstas};
183233294Sstas
184233294Sstasstatic const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
185233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
186233294Sstas    { 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL
187233294Sstas};
188233294Sstas
189233294Sstasstatic const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
190233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
191233294Sstas    { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
192233294Sstas};
193233294Sstas
194233294Sstasstatic const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
195233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_data = {
196233294Sstas    { 7, rk_UNCONST(rsa_oid) }, NULL
197233294Sstas};
198233294Sstas
199233294Sstasstatic const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
200233294Sstasconst AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
201233294Sstas    { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
202233294Sstas};
203233294Sstas
204233294Sstasstatic const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
205233294Sstasconst AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
206233294Sstas    { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
207233294Sstas};
208233294Sstas
209233294Sstasstatic const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
210233294Sstasconst AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
211233294Sstas    { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
212233294Sstas};
213233294Sstas
214233294Sstasstatic const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
215233294Sstasconst AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
216233294Sstas    { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
217233294Sstas};
218233294Sstas
219233294Sstas/*
220233294Sstas *
221233294Sstas */
222233294Sstas
223178825Sdfrstatic BIGNUM *
224178825Sdfrheim_int2BN(const heim_integer *i)
225178825Sdfr{
226178825Sdfr    BIGNUM *bn;
227178825Sdfr
228178825Sdfr    bn = BN_bin2bn(i->data, i->length, NULL);
229178825Sdfr    BN_set_negative(bn, i->negative);
230178825Sdfr    return bn;
231178825Sdfr}
232178825Sdfr
233178825Sdfr/*
234178825Sdfr *
235178825Sdfr */
236178825Sdfr
237178825Sdfrstatic int
238178825Sdfrset_digest_alg(DigestAlgorithmIdentifier *id,
239178825Sdfr	       const heim_oid *oid,
240178825Sdfr	       const void *param, size_t length)
241178825Sdfr{
242178825Sdfr    int ret;
243178825Sdfr    if (param) {
244178825Sdfr	id->parameters = malloc(sizeof(*id->parameters));
245178825Sdfr	if (id->parameters == NULL)
246178825Sdfr	    return ENOMEM;
247178825Sdfr	id->parameters->data = malloc(length);
248178825Sdfr	if (id->parameters->data == NULL) {
249178825Sdfr	    free(id->parameters);
250178825Sdfr	    id->parameters = NULL;
251178825Sdfr	    return ENOMEM;
252178825Sdfr	}
253178825Sdfr	memcpy(id->parameters->data, param, length);
254178825Sdfr	id->parameters->length = length;
255178825Sdfr    } else
256178825Sdfr	id->parameters = NULL;
257178825Sdfr    ret = der_copy_oid(oid, &id->algorithm);
258178825Sdfr    if (ret) {
259178825Sdfr	if (id->parameters) {
260178825Sdfr	    free(id->parameters->data);
261178825Sdfr	    free(id->parameters);
262178825Sdfr	    id->parameters = NULL;
263178825Sdfr	}
264178825Sdfr	return ret;
265178825Sdfr    }
266178825Sdfr    return 0;
267178825Sdfr}
268178825Sdfr
269233294Sstas#ifdef HAVE_OPENSSL
270233294Sstas
271233294Sstasstatic int
272233294Sstasheim_oid2ecnid(heim_oid *oid)
273233294Sstas{
274233294Sstas    /*
275233294Sstas     * Now map to openssl OID fun
276233294Sstas     */
277233294Sstas
278233294Sstas    if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
279233294Sstas	return NID_X9_62_prime256v1;
280233294Sstas    else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
281233294Sstas	return NID_secp160r1;
282233294Sstas    else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
283233294Sstas	return NID_secp160r2;
284233294Sstas
285233294Sstas    return -1;
286233294Sstas}
287233294Sstas
288233294Sstasstatic int
289233294Sstasparse_ECParameters(hx509_context context,
290233294Sstas		   heim_octet_string *parameters, int *nid)
291233294Sstas{
292233294Sstas    ECParameters ecparam;
293233294Sstas    size_t size;
294233294Sstas    int ret;
295233294Sstas
296233294Sstas    if (parameters == NULL) {
297233294Sstas	ret = HX509_PARSING_KEY_FAILED;
298233294Sstas	hx509_set_error_string(context, 0, ret,
299233294Sstas			       "EC parameters missing");
300233294Sstas	return ret;
301233294Sstas    }
302233294Sstas
303233294Sstas    ret = decode_ECParameters(parameters->data, parameters->length,
304233294Sstas			      &ecparam, &size);
305233294Sstas    if (ret) {
306233294Sstas	hx509_set_error_string(context, 0, ret,
307233294Sstas			       "Failed to decode EC parameters");
308233294Sstas	return ret;
309233294Sstas    }
310233294Sstas
311233294Sstas    if (ecparam.element != choice_ECParameters_namedCurve) {
312233294Sstas	free_ECParameters(&ecparam);
313233294Sstas	hx509_set_error_string(context, 0, ret,
314233294Sstas			       "EC parameters is not a named curve");
315233294Sstas	return HX509_CRYPTO_SIG_INVALID_FORMAT;
316233294Sstas    }
317233294Sstas
318233294Sstas    *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
319233294Sstas    free_ECParameters(&ecparam);
320233294Sstas    if (*nid == -1) {
321233294Sstas	hx509_set_error_string(context, 0, ret,
322233294Sstas			       "Failed to find matcing NID for EC curve");
323233294Sstas	return HX509_CRYPTO_SIG_INVALID_FORMAT;
324233294Sstas    }
325233294Sstas    return 0;
326233294Sstas}
327233294Sstas
328233294Sstas
329178825Sdfr/*
330178825Sdfr *
331178825Sdfr */
332178825Sdfr
333178825Sdfrstatic int
334233294Sstasecdsa_verify_signature(hx509_context context,
335233294Sstas		       const struct signature_alg *sig_alg,
336233294Sstas		       const Certificate *signer,
337233294Sstas		       const AlgorithmIdentifier *alg,
338233294Sstas		       const heim_octet_string *data,
339233294Sstas		       const heim_octet_string *sig)
340233294Sstas{
341233294Sstas    const AlgorithmIdentifier *digest_alg;
342233294Sstas    const SubjectPublicKeyInfo *spi;
343233294Sstas    heim_octet_string digest;
344233294Sstas    int ret;
345233294Sstas    EC_KEY *key = NULL;
346233294Sstas    int groupnid;
347233294Sstas    EC_GROUP *group;
348233294Sstas    const unsigned char *p;
349233294Sstas    long len;
350233294Sstas
351233294Sstas    digest_alg = sig_alg->digest_alg;
352233294Sstas
353233294Sstas    ret = _hx509_create_signature(context,
354233294Sstas				  NULL,
355233294Sstas				  digest_alg,
356233294Sstas				  data,
357233294Sstas				  NULL,
358233294Sstas				  &digest);
359233294Sstas    if (ret)
360233294Sstas	return ret;
361233294Sstas
362233294Sstas    /* set up EC KEY */
363233294Sstas    spi = &signer->tbsCertificate.subjectPublicKeyInfo;
364233294Sstas
365233294Sstas    if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
366233294Sstas	return HX509_CRYPTO_SIG_INVALID_FORMAT;
367233294Sstas
368233294Sstas#ifdef HAVE_OPENSSL
369233294Sstas    /*
370233294Sstas     * Find the group id
371233294Sstas     */
372233294Sstas
373233294Sstas    ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
374233294Sstas    if (ret) {
375233294Sstas	der_free_octet_string(&digest);
376233294Sstas	return ret;
377233294Sstas    }
378233294Sstas
379233294Sstas    /*
380233294Sstas     * Create group, key, parse key
381233294Sstas     */
382233294Sstas
383233294Sstas    key = EC_KEY_new();
384233294Sstas    group = EC_GROUP_new_by_curve_name(groupnid);
385233294Sstas    EC_KEY_set_group(key, group);
386233294Sstas    EC_GROUP_free(group);
387233294Sstas
388233294Sstas    p = spi->subjectPublicKey.data;
389233294Sstas    len = spi->subjectPublicKey.length / 8;
390233294Sstas
391233294Sstas    if (o2i_ECPublicKey(&key, &p, len) == NULL) {
392233294Sstas	EC_KEY_free(key);
393233294Sstas	return HX509_CRYPTO_SIG_INVALID_FORMAT;
394233294Sstas    }
395233294Sstas#else
396233294Sstas    key = SubjectPublicKeyInfo2EC_KEY(spi);
397233294Sstas#endif
398233294Sstas
399233294Sstas    ret = ECDSA_verify(-1, digest.data, digest.length,
400233294Sstas		       sig->data, sig->length, key);
401233294Sstas    der_free_octet_string(&digest);
402233294Sstas    EC_KEY_free(key);
403233294Sstas    if (ret != 1) {
404233294Sstas	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
405233294Sstas	return ret;
406233294Sstas    }
407233294Sstas
408233294Sstas    return 0;
409233294Sstas}
410233294Sstas
411233294Sstasstatic int
412233294Sstasecdsa_create_signature(hx509_context context,
413233294Sstas		       const struct signature_alg *sig_alg,
414233294Sstas		       const hx509_private_key signer,
415233294Sstas		       const AlgorithmIdentifier *alg,
416233294Sstas		       const heim_octet_string *data,
417233294Sstas		       AlgorithmIdentifier *signatureAlgorithm,
418233294Sstas		       heim_octet_string *sig)
419233294Sstas{
420233294Sstas    const AlgorithmIdentifier *digest_alg;
421233294Sstas    heim_octet_string indata;
422233294Sstas    const heim_oid *sig_oid;
423233294Sstas    unsigned int siglen;
424233294Sstas    int ret;
425233294Sstas
426233294Sstas    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
427233294Sstas	_hx509_abort("internal error passing private key to wrong ops");
428233294Sstas
429233294Sstas    sig_oid = sig_alg->sig_oid;
430233294Sstas    digest_alg = sig_alg->digest_alg;
431233294Sstas
432233294Sstas    if (signatureAlgorithm) {
433233294Sstas	ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
434233294Sstas	if (ret) {
435233294Sstas	    hx509_clear_error_string(context);
436233294Sstas	    goto error;
437233294Sstas	}
438233294Sstas    }
439233294Sstas
440233294Sstas    ret = _hx509_create_signature(context,
441233294Sstas				  NULL,
442233294Sstas				  digest_alg,
443233294Sstas				  data,
444233294Sstas				  NULL,
445233294Sstas				  &indata);
446233294Sstas    if (ret) {
447233294Sstas	if (signatureAlgorithm)
448233294Sstas	    free_AlgorithmIdentifier(signatureAlgorithm);
449233294Sstas	goto error;
450233294Sstas    }
451233294Sstas
452233294Sstas    sig->length = ECDSA_size(signer->private_key.ecdsa);
453233294Sstas    sig->data = malloc(sig->length);
454233294Sstas    if (sig->data == NULL) {
455233294Sstas	der_free_octet_string(&indata);
456233294Sstas	ret = ENOMEM;
457233294Sstas	hx509_set_error_string(context, 0, ret, "out of memory");
458233294Sstas	goto error;
459233294Sstas    }
460233294Sstas
461233294Sstas    siglen = sig->length;
462233294Sstas
463233294Sstas    ret = ECDSA_sign(-1, indata.data, indata.length,
464233294Sstas		     sig->data, &siglen, signer->private_key.ecdsa);
465233294Sstas    der_free_octet_string(&indata);
466233294Sstas    if (ret != 1) {
467233294Sstas	ret = HX509_CMS_FAILED_CREATE_SIGATURE;
468233294Sstas	hx509_set_error_string(context, 0, ret,
469233294Sstas			       "ECDSA sign failed: %d", ret);
470233294Sstas	goto error;
471233294Sstas    }
472233294Sstas    if (siglen > sig->length)
473233294Sstas	_hx509_abort("ECDSA signature prelen longer the output len");
474233294Sstas
475233294Sstas    sig->length = siglen;
476233294Sstas
477233294Sstas    return 0;
478233294Sstas error:
479233294Sstas    if (signatureAlgorithm)
480233294Sstas	free_AlgorithmIdentifier(signatureAlgorithm);
481233294Sstas    return ret;
482233294Sstas}
483233294Sstas
484233294Sstasstatic int
485233294Sstasecdsa_available(const hx509_private_key signer,
486233294Sstas		const AlgorithmIdentifier *sig_alg)
487233294Sstas{
488233294Sstas    const struct signature_alg *sig;
489233294Sstas    const EC_GROUP *group;
490233294Sstas    BN_CTX *bnctx = NULL;
491233294Sstas    BIGNUM *order = NULL;
492233294Sstas    int ret = 0;
493233294Sstas
494233294Sstas    if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
495233294Sstas	_hx509_abort("internal error passing private key to wrong ops");
496233294Sstas
497233294Sstas    sig = find_sig_alg(&sig_alg->algorithm);
498233294Sstas
499233294Sstas    if (sig == NULL || sig->digest_size == 0)
500233294Sstas	return 0;
501233294Sstas
502233294Sstas    group = EC_KEY_get0_group(signer->private_key.ecdsa);
503233294Sstas    if (group == NULL)
504233294Sstas	return 0;
505233294Sstas
506233294Sstas    bnctx = BN_CTX_new();
507233294Sstas    order = BN_new();
508233294Sstas    if (order == NULL)
509233294Sstas	goto err;
510233294Sstas
511233294Sstas    if (EC_GROUP_get_order(group, order, bnctx) != 1)
512233294Sstas	goto err;
513233294Sstas
514233294Sstas    if (BN_num_bytes(order) > sig->digest_size)
515233294Sstas	ret = 1;
516233294Sstas err:
517233294Sstas    if (bnctx)
518233294Sstas	BN_CTX_free(bnctx);
519233294Sstas    if (order)
520233294Sstas	BN_clear_free(order);
521233294Sstas
522233294Sstas    return ret;
523233294Sstas}
524233294Sstas
525233294Sstas
526233294Sstas#endif /* HAVE_OPENSSL */
527233294Sstas
528233294Sstas/*
529233294Sstas *
530233294Sstas */
531233294Sstas
532233294Sstasstatic int
533178825Sdfrrsa_verify_signature(hx509_context context,
534178825Sdfr		     const struct signature_alg *sig_alg,
535178825Sdfr		     const Certificate *signer,
536178825Sdfr		     const AlgorithmIdentifier *alg,
537178825Sdfr		     const heim_octet_string *data,
538178825Sdfr		     const heim_octet_string *sig)
539178825Sdfr{
540178825Sdfr    const SubjectPublicKeyInfo *spi;
541178825Sdfr    DigestInfo di;
542178825Sdfr    unsigned char *to;
543178825Sdfr    int tosize, retsize;
544178825Sdfr    int ret;
545178825Sdfr    RSA *rsa;
546178825Sdfr    size_t size;
547233294Sstas    const unsigned char *p;
548178825Sdfr
549178825Sdfr    memset(&di, 0, sizeof(di));
550178825Sdfr
551178825Sdfr    spi = &signer->tbsCertificate.subjectPublicKeyInfo;
552178825Sdfr
553233294Sstas    p = spi->subjectPublicKey.data;
554233294Sstas    size = spi->subjectPublicKey.length / 8;
555233294Sstas
556233294Sstas    rsa = d2i_RSAPublicKey(NULL, &p, size);
557178825Sdfr    if (rsa == NULL) {
558178825Sdfr	ret = ENOMEM;
559178825Sdfr	hx509_set_error_string(context, 0, ret, "out of memory");
560178825Sdfr	goto out;
561178825Sdfr    }
562178825Sdfr
563178825Sdfr    tosize = RSA_size(rsa);
564178825Sdfr    to = malloc(tosize);
565178825Sdfr    if (to == NULL) {
566178825Sdfr	ret = ENOMEM;
567178825Sdfr	hx509_set_error_string(context, 0, ret, "out of memory");
568178825Sdfr	goto out;
569178825Sdfr    }
570178825Sdfr
571233294Sstas    retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data,
572178825Sdfr				 to, rsa, RSA_PKCS1_PADDING);
573178825Sdfr    if (retsize <= 0) {
574178825Sdfr	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
575233294Sstas	hx509_set_error_string(context, 0, ret,
576178825Sdfr			       "RSA public decrypt failed: %d", retsize);
577178825Sdfr	free(to);
578178825Sdfr	goto out;
579178825Sdfr    }
580178825Sdfr    if (retsize > tosize)
581178825Sdfr	_hx509_abort("internal rsa decryption failure: ret > tosize");
582178825Sdfr
583178825Sdfr    if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) {
584178825Sdfr
585178825Sdfr	ret = decode_DigestInfo(to, retsize, &di, &size);
586178825Sdfr	free(to);
587178825Sdfr	if (ret) {
588178825Sdfr	    goto out;
589178825Sdfr	}
590233294Sstas
591178825Sdfr	/* Check for extra data inside the sigature */
592233294Sstas	if (size != (size_t)retsize) {
593178825Sdfr	    ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
594178825Sdfr	    hx509_set_error_string(context, 0, ret, "size from decryption mismatch");
595178825Sdfr	    goto out;
596178825Sdfr	}
597233294Sstas
598233294Sstas	if (sig_alg->digest_alg &&
599233294Sstas	    der_heim_oid_cmp(&di.digestAlgorithm.algorithm,
600233294Sstas			     &sig_alg->digest_alg->algorithm) != 0)
601178825Sdfr	{
602178825Sdfr	    ret = HX509_CRYPTO_OID_MISMATCH;
603178825Sdfr	    hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch");
604178825Sdfr	    goto out;
605178825Sdfr	}
606233294Sstas
607178825Sdfr	/* verify that the parameters are NULL or the NULL-type */
608178825Sdfr	if (di.digestAlgorithm.parameters != NULL &&
609178825Sdfr	    (di.digestAlgorithm.parameters->length != 2 ||
610178825Sdfr	     memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0))
611178825Sdfr	{
612178825Sdfr	    ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
613178825Sdfr	    hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature");
614178825Sdfr	    goto out;
615178825Sdfr	}
616178825Sdfr
617178825Sdfr	ret = _hx509_verify_signature(context,
618178825Sdfr				      NULL,
619178825Sdfr				      &di.digestAlgorithm,
620178825Sdfr				      data,
621178825Sdfr				      &di.digest);
622178825Sdfr    } else {
623233294Sstas	if ((size_t)retsize != data->length ||
624233294Sstas	    ct_memcmp(to, data->data, retsize) != 0)
625178825Sdfr	{
626178825Sdfr	    ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
627178825Sdfr	    hx509_set_error_string(context, 0, ret, "RSA Signature incorrect");
628178825Sdfr	    goto out;
629178825Sdfr	}
630178825Sdfr	free(to);
631178825Sdfr    }
632233294Sstas    ret = 0;
633178825Sdfr
634178825Sdfr out:
635178825Sdfr    free_DigestInfo(&di);
636233294Sstas    if (rsa)
637233294Sstas	RSA_free(rsa);
638178825Sdfr    return ret;
639178825Sdfr}
640178825Sdfr
641178825Sdfrstatic int
642178825Sdfrrsa_create_signature(hx509_context context,
643178825Sdfr		     const struct signature_alg *sig_alg,
644178825Sdfr		     const hx509_private_key signer,
645178825Sdfr		     const AlgorithmIdentifier *alg,
646178825Sdfr		     const heim_octet_string *data,
647178825Sdfr		     AlgorithmIdentifier *signatureAlgorithm,
648178825Sdfr		     heim_octet_string *sig)
649178825Sdfr{
650178825Sdfr    const AlgorithmIdentifier *digest_alg;
651178825Sdfr    heim_octet_string indata;
652178825Sdfr    const heim_oid *sig_oid;
653178825Sdfr    size_t size;
654178825Sdfr    int ret;
655233294Sstas
656233294Sstas    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0)
657233294Sstas	return HX509_ALG_NOT_SUPP;
658233294Sstas
659178825Sdfr    if (alg)
660178825Sdfr	sig_oid = &alg->algorithm;
661178825Sdfr    else
662178825Sdfr	sig_oid = signer->signature_alg;
663178825Sdfr
664233294Sstas    if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) {
665233294Sstas	digest_alg = hx509_signature_sha512();
666233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) {
667233294Sstas	digest_alg = hx509_signature_sha384();
668233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) {
669178825Sdfr	digest_alg = hx509_signature_sha256();
670233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) {
671178825Sdfr	digest_alg = hx509_signature_sha1();
672233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
673178825Sdfr	digest_alg = hx509_signature_md5();
674233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
675178825Sdfr	digest_alg = hx509_signature_md5();
676233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) {
677178825Sdfr	digest_alg = hx509_signature_sha1();
678233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
679178825Sdfr	digest_alg = hx509_signature_sha1();
680233294Sstas    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) {
681178825Sdfr	digest_alg = NULL;
682178825Sdfr    } else
683178825Sdfr	return HX509_ALG_NOT_SUPP;
684178825Sdfr
685178825Sdfr    if (signatureAlgorithm) {
686178825Sdfr	ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
687178825Sdfr	if (ret) {
688178825Sdfr	    hx509_clear_error_string(context);
689178825Sdfr	    return ret;
690178825Sdfr	}
691178825Sdfr    }
692178825Sdfr
693178825Sdfr    if (digest_alg) {
694178825Sdfr	DigestInfo di;
695178825Sdfr	memset(&di, 0, sizeof(di));
696178825Sdfr
697178825Sdfr	ret = _hx509_create_signature(context,
698178825Sdfr				      NULL,
699178825Sdfr				      digest_alg,
700178825Sdfr				      data,
701178825Sdfr				      &di.digestAlgorithm,
702178825Sdfr				      &di.digest);
703178825Sdfr	if (ret)
704178825Sdfr	    return ret;
705178825Sdfr	ASN1_MALLOC_ENCODE(DigestInfo,
706178825Sdfr			   indata.data,
707178825Sdfr			   indata.length,
708178825Sdfr			   &di,
709178825Sdfr			   &size,
710178825Sdfr			   ret);
711178825Sdfr	free_DigestInfo(&di);
712178825Sdfr	if (ret) {
713178825Sdfr	    hx509_set_error_string(context, 0, ret, "out of memory");
714178825Sdfr	    return ret;
715178825Sdfr	}
716178825Sdfr	if (indata.length != size)
717178825Sdfr	    _hx509_abort("internal ASN.1 encoder error");
718178825Sdfr    } else {
719178825Sdfr	indata = *data;
720178825Sdfr    }
721178825Sdfr
722178825Sdfr    sig->length = RSA_size(signer->private_key.rsa);
723178825Sdfr    sig->data = malloc(sig->length);
724178825Sdfr    if (sig->data == NULL) {
725178825Sdfr	der_free_octet_string(&indata);
726178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
727178825Sdfr	return ENOMEM;
728178825Sdfr    }
729178825Sdfr
730233294Sstas    ret = RSA_private_encrypt(indata.length, indata.data,
731233294Sstas			      sig->data,
732178825Sdfr			      signer->private_key.rsa,
733178825Sdfr			      RSA_PKCS1_PADDING);
734178825Sdfr    if (indata.data != data->data)
735178825Sdfr	der_free_octet_string(&indata);
736178825Sdfr    if (ret <= 0) {
737178825Sdfr	ret = HX509_CMS_FAILED_CREATE_SIGATURE;
738178825Sdfr	hx509_set_error_string(context, 0, ret,
739233294Sstas			       "RSA private encrypt failed: %d", ret);
740178825Sdfr	return ret;
741178825Sdfr    }
742233294Sstas    if ((size_t)ret > sig->length)
743178825Sdfr	_hx509_abort("RSA signature prelen longer the output len");
744178825Sdfr
745178825Sdfr    sig->length = ret;
746233294Sstas
747178825Sdfr    return 0;
748178825Sdfr}
749178825Sdfr
750178825Sdfrstatic int
751178825Sdfrrsa_private_key_import(hx509_context context,
752233294Sstas		       const AlgorithmIdentifier *keyai,
753178825Sdfr		       const void *data,
754178825Sdfr		       size_t len,
755233294Sstas		       hx509_key_format_t format,
756178825Sdfr		       hx509_private_key private_key)
757178825Sdfr{
758233294Sstas    switch (format) {
759233294Sstas    case HX509_KEY_FORMAT_DER: {
760233294Sstas	const unsigned char *p = data;
761178825Sdfr
762233294Sstas	private_key->private_key.rsa =
763233294Sstas	    d2i_RSAPrivateKey(NULL, &p, len);
764233294Sstas	if (private_key->private_key.rsa == NULL) {
765233294Sstas	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
766233294Sstas				   "Failed to parse RSA key");
767233294Sstas	    return HX509_PARSING_KEY_FAILED;
768233294Sstas	}
769233294Sstas	private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
770233294Sstas	break;
771233294Sstas
772178825Sdfr    }
773233294Sstas    default:
774233294Sstas	return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
775233294Sstas    }
776178825Sdfr
777178825Sdfr    return 0;
778178825Sdfr}
779178825Sdfr
780178825Sdfrstatic int
781178825Sdfrrsa_private_key2SPKI(hx509_context context,
782178825Sdfr		     hx509_private_key private_key,
783178825Sdfr		     SubjectPublicKeyInfo *spki)
784178825Sdfr{
785178825Sdfr    int len, ret;
786178825Sdfr
787178825Sdfr    memset(spki, 0, sizeof(*spki));
788178825Sdfr
789178825Sdfr    len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
790178825Sdfr
791178825Sdfr    spki->subjectPublicKey.data = malloc(len);
792178825Sdfr    if (spki->subjectPublicKey.data == NULL) {
793178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
794178825Sdfr	return ENOMEM;
795178825Sdfr    }
796178825Sdfr    spki->subjectPublicKey.length = len * 8;
797178825Sdfr
798233294Sstas    ret = set_digest_alg(&spki->algorithm, ASN1_OID_ID_PKCS1_RSAENCRYPTION,
799178825Sdfr			 "\x05\x00", 2);
800178825Sdfr    if (ret) {
801178825Sdfr	hx509_set_error_string(context, 0, ret, "malloc - out of memory");
802178825Sdfr	free(spki->subjectPublicKey.data);
803178825Sdfr	spki->subjectPublicKey.data = NULL;
804178825Sdfr	spki->subjectPublicKey.length = 0;
805178825Sdfr	return ret;
806178825Sdfr    }
807178825Sdfr
808178825Sdfr    {
809178825Sdfr	unsigned char *pp = spki->subjectPublicKey.data;
810178825Sdfr	i2d_RSAPublicKey(private_key->private_key.rsa, &pp);
811178825Sdfr    }
812178825Sdfr
813178825Sdfr    return 0;
814178825Sdfr}
815178825Sdfr
816178825Sdfrstatic int
817233294Sstasrsa_generate_private_key(hx509_context context,
818178825Sdfr			 struct hx509_generate_private_context *ctx,
819178825Sdfr			 hx509_private_key private_key)
820178825Sdfr{
821178825Sdfr    BIGNUM *e;
822178825Sdfr    int ret;
823178825Sdfr    unsigned long bits;
824178825Sdfr
825178825Sdfr    static const int default_rsa_e = 65537;
826233294Sstas    static const int default_rsa_bits = 2048;
827178825Sdfr
828178825Sdfr    private_key->private_key.rsa = RSA_new();
829178825Sdfr    if (private_key->private_key.rsa == NULL) {
830178825Sdfr	hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
831178825Sdfr			       "Failed to generate RSA key");
832178825Sdfr	return HX509_PARSING_KEY_FAILED;
833178825Sdfr    }
834233294Sstas
835178825Sdfr    e = BN_new();
836178825Sdfr    BN_set_word(e, default_rsa_e);
837178825Sdfr
838178825Sdfr    bits = default_rsa_bits;
839178825Sdfr
840178825Sdfr    if (ctx->num_bits)
841178825Sdfr	bits = ctx->num_bits;
842178825Sdfr
843178825Sdfr    ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL);
844178825Sdfr    BN_free(e);
845178825Sdfr    if (ret != 1) {
846178825Sdfr	hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
847178825Sdfr			       "Failed to generate RSA key");
848178825Sdfr	return HX509_PARSING_KEY_FAILED;
849178825Sdfr    }
850233294Sstas    private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
851178825Sdfr
852178825Sdfr    return 0;
853178825Sdfr}
854178825Sdfr
855233294Sstasstatic int
856178825Sdfrrsa_private_key_export(hx509_context context,
857178825Sdfr		       const hx509_private_key key,
858233294Sstas		       hx509_key_format_t format,
859178825Sdfr		       heim_octet_string *data)
860178825Sdfr{
861178825Sdfr    int ret;
862178825Sdfr
863178825Sdfr    data->data = NULL;
864178825Sdfr    data->length = 0;
865178825Sdfr
866233294Sstas    switch (format) {
867233294Sstas    case HX509_KEY_FORMAT_DER:
868233294Sstas
869233294Sstas	ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL);
870233294Sstas	if (ret <= 0) {
871233294Sstas	    ret = EINVAL;
872233294Sstas	    hx509_set_error_string(context, 0, ret,
873178825Sdfr			       "Private key is not exportable");
874233294Sstas	    return ret;
875233294Sstas	}
876178825Sdfr
877233294Sstas	data->data = malloc(ret);
878233294Sstas	if (data->data == NULL) {
879233294Sstas	    ret = ENOMEM;
880233294Sstas	    hx509_set_error_string(context, 0, ret, "malloc out of memory");
881233294Sstas	    return ret;
882233294Sstas	}
883233294Sstas	data->length = ret;
884233294Sstas
885233294Sstas	{
886233294Sstas	    unsigned char *p = data->data;
887233294Sstas	    i2d_RSAPrivateKey(key->private_key.rsa, &p);
888233294Sstas	}
889233294Sstas	break;
890233294Sstas    default:
891233294Sstas	return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
892178825Sdfr    }
893178825Sdfr
894178825Sdfr    return 0;
895178825Sdfr}
896178825Sdfr
897178825Sdfrstatic BIGNUM *
898233294Sstasrsa_get_internal(hx509_context context,
899233294Sstas		 hx509_private_key key,
900233294Sstas		 const char *type)
901178825Sdfr{
902178825Sdfr    if (strcasecmp(type, "rsa-modulus") == 0) {
903178825Sdfr	return BN_dup(key->private_key.rsa->n);
904178825Sdfr    } else if (strcasecmp(type, "rsa-exponent") == 0) {
905178825Sdfr	return BN_dup(key->private_key.rsa->e);
906178825Sdfr    } else
907178825Sdfr	return NULL;
908178825Sdfr}
909178825Sdfr
910178825Sdfr
911178825Sdfr
912178825Sdfrstatic hx509_private_key_ops rsa_private_key_ops = {
913178825Sdfr    "RSA PRIVATE KEY",
914233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
915233294Sstas    NULL,
916178825Sdfr    rsa_private_key2SPKI,
917178825Sdfr    rsa_private_key_export,
918178825Sdfr    rsa_private_key_import,
919178825Sdfr    rsa_generate_private_key,
920178825Sdfr    rsa_get_internal
921178825Sdfr};
922178825Sdfr
923233294Sstas#ifdef HAVE_OPENSSL
924178825Sdfr
925233294Sstasstatic int
926233294Sstasecdsa_private_key2SPKI(hx509_context context,
927233294Sstas		       hx509_private_key private_key,
928233294Sstas		       SubjectPublicKeyInfo *spki)
929233294Sstas{
930233294Sstas    memset(spki, 0, sizeof(*spki));
931233294Sstas    return ENOMEM;
932233294Sstas}
933233294Sstas
934233294Sstasstatic int
935233294Sstasecdsa_private_key_export(hx509_context context,
936233294Sstas			 const hx509_private_key key,
937233294Sstas			 hx509_key_format_t format,
938233294Sstas			 heim_octet_string *data)
939233294Sstas{
940233294Sstas    return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
941233294Sstas}
942233294Sstas
943233294Sstasstatic int
944233294Sstasecdsa_private_key_import(hx509_context context,
945233294Sstas			 const AlgorithmIdentifier *keyai,
946233294Sstas			 const void *data,
947233294Sstas			 size_t len,
948233294Sstas			 hx509_key_format_t format,
949233294Sstas			 hx509_private_key private_key)
950233294Sstas{
951233294Sstas    const unsigned char *p = data;
952233294Sstas    EC_KEY **pkey = NULL;
953233294Sstas
954233294Sstas    if (keyai->parameters) {
955233294Sstas	EC_GROUP *group;
956233294Sstas	int groupnid;
957233294Sstas	EC_KEY *key;
958233294Sstas	int ret;
959233294Sstas
960233294Sstas	ret = parse_ECParameters(context, keyai->parameters, &groupnid);
961233294Sstas	if (ret)
962233294Sstas	    return ret;
963233294Sstas
964233294Sstas	key = EC_KEY_new();
965233294Sstas	if (key == NULL)
966233294Sstas	    return ENOMEM;
967233294Sstas
968233294Sstas	group = EC_GROUP_new_by_curve_name(groupnid);
969233294Sstas	if (group == NULL) {
970233294Sstas	    EC_KEY_free(key);
971233294Sstas	    return ENOMEM;
972233294Sstas	}
973233294Sstas	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
974233294Sstas	if (EC_KEY_set_group(key, group) == 0) {
975233294Sstas	    EC_KEY_free(key);
976233294Sstas	    EC_GROUP_free(group);
977233294Sstas	    return ENOMEM;
978233294Sstas	}
979233294Sstas	EC_GROUP_free(group);
980233294Sstas	pkey = &key;
981233294Sstas    }
982233294Sstas
983233294Sstas    switch (format) {
984233294Sstas    case HX509_KEY_FORMAT_DER:
985233294Sstas
986233294Sstas	private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
987233294Sstas	if (private_key->private_key.ecdsa == NULL) {
988233294Sstas	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
989233294Sstas				   "Failed to parse EC private key");
990233294Sstas	    return HX509_PARSING_KEY_FAILED;
991233294Sstas	}
992233294Sstas	private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
993233294Sstas	break;
994233294Sstas
995233294Sstas    default:
996233294Sstas	return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
997233294Sstas    }
998233294Sstas
999233294Sstas    return 0;
1000233294Sstas}
1001233294Sstas
1002233294Sstasstatic int
1003233294Sstasecdsa_generate_private_key(hx509_context context,
1004233294Sstas			   struct hx509_generate_private_context *ctx,
1005233294Sstas			   hx509_private_key private_key)
1006233294Sstas{
1007233294Sstas    return ENOMEM;
1008233294Sstas}
1009233294Sstas
1010233294Sstasstatic BIGNUM *
1011233294Sstasecdsa_get_internal(hx509_context context,
1012233294Sstas		   hx509_private_key key,
1013233294Sstas		   const char *type)
1014233294Sstas{
1015233294Sstas    return NULL;
1016233294Sstas}
1017233294Sstas
1018233294Sstas
1019233294Sstasstatic hx509_private_key_ops ecdsa_private_key_ops = {
1020233294Sstas    "EC PRIVATE KEY",
1021233294Sstas    ASN1_OID_ID_ECPUBLICKEY,
1022233294Sstas    ecdsa_available,
1023233294Sstas    ecdsa_private_key2SPKI,
1024233294Sstas    ecdsa_private_key_export,
1025233294Sstas    ecdsa_private_key_import,
1026233294Sstas    ecdsa_generate_private_key,
1027233294Sstas    ecdsa_get_internal
1028233294Sstas};
1029233294Sstas
1030233294Sstas#endif /* HAVE_OPENSSL */
1031233294Sstas
1032178825Sdfr/*
1033178825Sdfr *
1034178825Sdfr */
1035178825Sdfr
1036178825Sdfrstatic int
1037178825Sdfrdsa_verify_signature(hx509_context context,
1038178825Sdfr		     const struct signature_alg *sig_alg,
1039178825Sdfr		     const Certificate *signer,
1040178825Sdfr		     const AlgorithmIdentifier *alg,
1041178825Sdfr		     const heim_octet_string *data,
1042178825Sdfr		     const heim_octet_string *sig)
1043178825Sdfr{
1044178825Sdfr    const SubjectPublicKeyInfo *spi;
1045178825Sdfr    DSAPublicKey pk;
1046178825Sdfr    DSAParams param;
1047178825Sdfr    size_t size;
1048178825Sdfr    DSA *dsa;
1049178825Sdfr    int ret;
1050178825Sdfr
1051178825Sdfr    spi = &signer->tbsCertificate.subjectPublicKeyInfo;
1052178825Sdfr
1053178825Sdfr    dsa = DSA_new();
1054178825Sdfr    if (dsa == NULL) {
1055178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1056178825Sdfr	return ENOMEM;
1057178825Sdfr    }
1058178825Sdfr
1059178825Sdfr    ret = decode_DSAPublicKey(spi->subjectPublicKey.data,
1060178825Sdfr			      spi->subjectPublicKey.length / 8,
1061178825Sdfr			      &pk, &size);
1062178825Sdfr    if (ret)
1063178825Sdfr	goto out;
1064178825Sdfr
1065178825Sdfr    dsa->pub_key = heim_int2BN(&pk);
1066178825Sdfr
1067178825Sdfr    free_DSAPublicKey(&pk);
1068178825Sdfr
1069178825Sdfr    if (dsa->pub_key == NULL) {
1070178825Sdfr	ret = ENOMEM;
1071178825Sdfr	hx509_set_error_string(context, 0, ret, "out of memory");
1072178825Sdfr	goto out;
1073178825Sdfr    }
1074178825Sdfr
1075178825Sdfr    if (spi->algorithm.parameters == NULL) {
1076178825Sdfr	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
1077178825Sdfr	hx509_set_error_string(context, 0, ret, "DSA parameters missing");
1078178825Sdfr	goto out;
1079178825Sdfr    }
1080178825Sdfr
1081178825Sdfr    ret = decode_DSAParams(spi->algorithm.parameters->data,
1082178825Sdfr			   spi->algorithm.parameters->length,
1083178825Sdfr			   &param,
1084178825Sdfr			   &size);
1085178825Sdfr    if (ret) {
1086178825Sdfr	hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode");
1087178825Sdfr	goto out;
1088178825Sdfr    }
1089178825Sdfr
1090178825Sdfr    dsa->p = heim_int2BN(&param.p);
1091178825Sdfr    dsa->q = heim_int2BN(&param.q);
1092178825Sdfr    dsa->g = heim_int2BN(&param.g);
1093178825Sdfr
1094178825Sdfr    free_DSAParams(&param);
1095178825Sdfr
1096178825Sdfr    if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
1097178825Sdfr	ret = ENOMEM;
1098178825Sdfr	hx509_set_error_string(context, 0, ret, "out of memory");
1099178825Sdfr	goto out;
1100178825Sdfr    }
1101178825Sdfr
1102178825Sdfr    ret = DSA_verify(-1, data->data, data->length,
1103178825Sdfr		     (unsigned char*)sig->data, sig->length,
1104178825Sdfr		     dsa);
1105178825Sdfr    if (ret == 1)
1106178825Sdfr	ret = 0;
1107178825Sdfr    else if (ret == 0 || ret == -1) {
1108178825Sdfr	ret = HX509_CRYPTO_BAD_SIGNATURE;
1109178825Sdfr	hx509_set_error_string(context, 0, ret, "BAD DSA sigature");
1110178825Sdfr    } else {
1111178825Sdfr	ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
1112178825Sdfr	hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature");
1113178825Sdfr    }
1114178825Sdfr
1115178825Sdfr out:
1116178825Sdfr    DSA_free(dsa);
1117178825Sdfr
1118178825Sdfr    return ret;
1119178825Sdfr}
1120178825Sdfr
1121178825Sdfr#if 0
1122178825Sdfrstatic int
1123178825Sdfrdsa_parse_private_key(hx509_context context,
1124178825Sdfr		      const void *data,
1125178825Sdfr		      size_t len,
1126178825Sdfr		      hx509_private_key private_key)
1127178825Sdfr{
1128178825Sdfr    const unsigned char *p = data;
1129178825Sdfr
1130233294Sstas    private_key->private_key.dsa =
1131178825Sdfr	d2i_DSAPrivateKey(NULL, &p, len);
1132178825Sdfr    if (private_key->private_key.dsa == NULL)
1133178825Sdfr	return EINVAL;
1134233294Sstas    private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1;
1135178825Sdfr
1136178825Sdfr    return 0;
1137178825Sdfr/* else */
1138178825Sdfr    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
1139178825Sdfr			   "No support to parse DSA keys");
1140178825Sdfr    return HX509_PARSING_KEY_FAILED;
1141178825Sdfr}
1142178825Sdfr#endif
1143178825Sdfr
1144178825Sdfrstatic int
1145233294Sstasevp_md_create_signature(hx509_context context,
1146178825Sdfr			const struct signature_alg *sig_alg,
1147178825Sdfr			const hx509_private_key signer,
1148178825Sdfr			const AlgorithmIdentifier *alg,
1149178825Sdfr			const heim_octet_string *data,
1150178825Sdfr			AlgorithmIdentifier *signatureAlgorithm,
1151178825Sdfr			heim_octet_string *sig)
1152178825Sdfr{
1153233294Sstas    size_t sigsize = EVP_MD_size(sig_alg->evp_md());
1154233294Sstas    EVP_MD_CTX *ctx;
1155233294Sstas
1156178825Sdfr    memset(sig, 0, sizeof(*sig));
1157178825Sdfr
1158178825Sdfr    if (signatureAlgorithm) {
1159178825Sdfr	int ret;
1160233294Sstas	ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
1161178825Sdfr			     "\x05\x00", 2);
1162178825Sdfr	if (ret)
1163178825Sdfr	    return ret;
1164178825Sdfr    }
1165178825Sdfr
1166233294Sstas
1167233294Sstas    sig->data = malloc(sigsize);
1168178825Sdfr    if (sig->data == NULL) {
1169178825Sdfr	sig->length = 0;
1170178825Sdfr	return ENOMEM;
1171178825Sdfr    }
1172233294Sstas    sig->length = sigsize;
1173178825Sdfr
1174233294Sstas    ctx = EVP_MD_CTX_create();
1175233294Sstas    EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);
1176233294Sstas    EVP_DigestUpdate(ctx, data->data, data->length);
1177233294Sstas    EVP_DigestFinal_ex(ctx, sig->data, NULL);
1178233294Sstas    EVP_MD_CTX_destroy(ctx);
1179178825Sdfr
1180233294Sstas
1181178825Sdfr    return 0;
1182178825Sdfr}
1183178825Sdfr
1184178825Sdfrstatic int
1185233294Sstasevp_md_verify_signature(hx509_context context,
1186178825Sdfr			const struct signature_alg *sig_alg,
1187178825Sdfr			const Certificate *signer,
1188178825Sdfr			const AlgorithmIdentifier *alg,
1189178825Sdfr			const heim_octet_string *data,
1190178825Sdfr			const heim_octet_string *sig)
1191178825Sdfr{
1192233294Sstas    unsigned char digest[EVP_MAX_MD_SIZE];
1193233294Sstas    EVP_MD_CTX *ctx;
1194233294Sstas    size_t sigsize = EVP_MD_size(sig_alg->evp_md());
1195233294Sstas
1196233294Sstas    if (sig->length != sigsize || sigsize > sizeof(digest)) {
1197178825Sdfr	hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
1198178825Sdfr			       "SHA256 sigature have wrong length");
1199178825Sdfr	return HX509_CRYPTO_SIG_INVALID_FORMAT;
1200178825Sdfr    }
1201178825Sdfr
1202233294Sstas    ctx = EVP_MD_CTX_create();
1203233294Sstas    EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);
1204233294Sstas    EVP_DigestUpdate(ctx, data->data, data->length);
1205233294Sstas    EVP_DigestFinal_ex(ctx, digest, NULL);
1206233294Sstas    EVP_MD_CTX_destroy(ctx);
1207233294Sstas
1208233294Sstas    if (ct_memcmp(digest, sig->data, sigsize) != 0) {
1209178825Sdfr	hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE,
1210233294Sstas			       "Bad %s sigature", sig_alg->name);
1211178825Sdfr	return HX509_CRYPTO_BAD_SIGNATURE;
1212178825Sdfr    }
1213178825Sdfr
1214178825Sdfr    return 0;
1215178825Sdfr}
1216178825Sdfr
1217233294Sstas#ifdef HAVE_OPENSSL
1218178825Sdfr
1219233294Sstasstatic const struct signature_alg ecdsa_with_sha256_alg = {
1220233294Sstas    "ecdsa-with-sha256",
1221233294Sstas    ASN1_OID_ID_ECDSA_WITH_SHA256,
1222233294Sstas    &_hx509_signature_ecdsa_with_sha256_data,
1223233294Sstas    ASN1_OID_ID_ECPUBLICKEY,
1224233294Sstas    &_hx509_signature_sha256_data,
1225233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1226233294Sstas    0,
1227233294Sstas    NULL,
1228233294Sstas    ecdsa_verify_signature,
1229233294Sstas    ecdsa_create_signature,
1230233294Sstas    32
1231233294Sstas};
1232178825Sdfr
1233233294Sstasstatic const struct signature_alg ecdsa_with_sha1_alg = {
1234233294Sstas    "ecdsa-with-sha1",
1235233294Sstas    ASN1_OID_ID_ECDSA_WITH_SHA1,
1236233294Sstas    &_hx509_signature_ecdsa_with_sha1_data,
1237233294Sstas    ASN1_OID_ID_ECPUBLICKEY,
1238233294Sstas    &_hx509_signature_sha1_data,
1239233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1240233294Sstas    0,
1241233294Sstas    NULL,
1242233294Sstas    ecdsa_verify_signature,
1243233294Sstas    ecdsa_create_signature,
1244233294Sstas    20
1245233294Sstas};
1246178825Sdfr
1247233294Sstas#endif
1248178825Sdfr
1249178825Sdfrstatic const struct signature_alg heim_rsa_pkcs1_x509 = {
1250178825Sdfr    "rsa-pkcs1-x509",
1251233294Sstas    ASN1_OID_ID_HEIM_RSA_PKCS1_X509,
1252233294Sstas    &_hx509_signature_rsa_pkcs1_x509_data,
1253233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1254178825Sdfr    NULL,
1255178825Sdfr    PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
1256233294Sstas    0,
1257233294Sstas    NULL,
1258178825Sdfr    rsa_verify_signature,
1259233294Sstas    rsa_create_signature,
1260233294Sstas    0
1261178825Sdfr};
1262178825Sdfr
1263178825Sdfrstatic const struct signature_alg pkcs1_rsa_sha1_alg = {
1264178825Sdfr    "rsa",
1265233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1266233294Sstas    &_hx509_signature_rsa_with_sha1_data,
1267233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1268178825Sdfr    NULL,
1269233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1270233294Sstas    0,
1271233294Sstas    NULL,
1272178825Sdfr    rsa_verify_signature,
1273233294Sstas    rsa_create_signature,
1274233294Sstas    0
1275178825Sdfr};
1276178825Sdfr
1277233294Sstasstatic const struct signature_alg rsa_with_sha512_alg = {
1278233294Sstas    "rsa-with-sha512",
1279233294Sstas    ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION,
1280233294Sstas    &_hx509_signature_rsa_with_sha512_data,
1281233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1282233294Sstas    &_hx509_signature_sha512_data,
1283233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1284233294Sstas    0,
1285233294Sstas    NULL,
1286233294Sstas    rsa_verify_signature,
1287233294Sstas    rsa_create_signature,
1288233294Sstas    0
1289233294Sstas};
1290233294Sstas
1291233294Sstasstatic const struct signature_alg rsa_with_sha384_alg = {
1292233294Sstas    "rsa-with-sha384",
1293233294Sstas    ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION,
1294233294Sstas    &_hx509_signature_rsa_with_sha384_data,
1295233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1296233294Sstas    &_hx509_signature_sha384_data,
1297233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1298233294Sstas    0,
1299233294Sstas    NULL,
1300233294Sstas    rsa_verify_signature,
1301233294Sstas    rsa_create_signature,
1302233294Sstas    0
1303233294Sstas};
1304233294Sstas
1305178825Sdfrstatic const struct signature_alg rsa_with_sha256_alg = {
1306178825Sdfr    "rsa-with-sha256",
1307233294Sstas    ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION,
1308233294Sstas    &_hx509_signature_rsa_with_sha256_data,
1309233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1310233294Sstas    &_hx509_signature_sha256_data,
1311233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1312233294Sstas    0,
1313233294Sstas    NULL,
1314178825Sdfr    rsa_verify_signature,
1315233294Sstas    rsa_create_signature,
1316233294Sstas    0
1317178825Sdfr};
1318178825Sdfr
1319178825Sdfrstatic const struct signature_alg rsa_with_sha1_alg = {
1320178825Sdfr    "rsa-with-sha1",
1321233294Sstas    ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION,
1322233294Sstas    &_hx509_signature_rsa_with_sha1_data,
1323233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1324233294Sstas    &_hx509_signature_sha1_data,
1325233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1326233294Sstas    0,
1327233294Sstas    NULL,
1328178825Sdfr    rsa_verify_signature,
1329233294Sstas    rsa_create_signature,
1330233294Sstas    0
1331178825Sdfr};
1332178825Sdfr
1333233294Sstasstatic const struct signature_alg rsa_with_sha1_alg_secsig = {
1334233294Sstas    "rsa-with-sha1",
1335233294Sstas    ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION,
1336233294Sstas    &_hx509_signature_rsa_with_sha1_data,
1337233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1338233294Sstas    &_hx509_signature_sha1_data,
1339233294Sstas    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
1340233294Sstas    0,
1341233294Sstas    NULL,
1342178825Sdfr    rsa_verify_signature,
1343233294Sstas    rsa_create_signature,
1344233294Sstas    0
1345178825Sdfr};
1346178825Sdfr
1347233294Sstasstatic const struct signature_alg rsa_with_md5_alg = {
1348233294Sstas    "rsa-with-md5",
1349233294Sstas    ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION,
1350233294Sstas    &_hx509_signature_rsa_with_md5_data,
1351233294Sstas    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
1352233294Sstas    &_hx509_signature_md5_data,
1353178825Sdfr    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
1354233294Sstas    1230739889,
1355233294Sstas    NULL,
1356178825Sdfr    rsa_verify_signature,
1357233294Sstas    rsa_create_signature,
1358233294Sstas    0
1359178825Sdfr};
1360178825Sdfr
1361178825Sdfrstatic const struct signature_alg dsa_sha1_alg = {
1362178825Sdfr    "dsa-with-sha1",
1363233294Sstas    ASN1_OID_ID_DSA_WITH_SHA1,
1364178825Sdfr    NULL,
1365233294Sstas    ASN1_OID_ID_DSA,
1366233294Sstas    &_hx509_signature_sha1_data,
1367178825Sdfr    PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
1368233294Sstas    0,
1369233294Sstas    NULL,
1370178825Sdfr    dsa_verify_signature,
1371178825Sdfr    /* create_signature */ NULL,
1372233294Sstas    0
1373178825Sdfr};
1374178825Sdfr
1375233294Sstasstatic const struct signature_alg sha512_alg = {
1376233294Sstas    "sha-512",
1377233294Sstas    ASN1_OID_ID_SHA512,
1378233294Sstas    &_hx509_signature_sha512_data,
1379233294Sstas    NULL,
1380233294Sstas    NULL,
1381233294Sstas    SIG_DIGEST,
1382233294Sstas    0,
1383233294Sstas    EVP_sha512,
1384233294Sstas    evp_md_verify_signature,
1385233294Sstas    evp_md_create_signature,
1386233294Sstas    0
1387233294Sstas};
1388233294Sstas
1389233294Sstasstatic const struct signature_alg sha384_alg = {
1390233294Sstas    "sha-384",
1391233294Sstas    ASN1_OID_ID_SHA512,
1392233294Sstas    &_hx509_signature_sha384_data,
1393233294Sstas    NULL,
1394233294Sstas    NULL,
1395233294Sstas    SIG_DIGEST,
1396233294Sstas    0,
1397233294Sstas    EVP_sha384,
1398233294Sstas    evp_md_verify_signature,
1399233294Sstas    evp_md_create_signature,
1400233294Sstas    0
1401233294Sstas};
1402233294Sstas
1403178825Sdfrstatic const struct signature_alg sha256_alg = {
1404178825Sdfr    "sha-256",
1405233294Sstas    ASN1_OID_ID_SHA256,
1406233294Sstas    &_hx509_signature_sha256_data,
1407178825Sdfr    NULL,
1408178825Sdfr    NULL,
1409178825Sdfr    SIG_DIGEST,
1410233294Sstas    0,
1411233294Sstas    EVP_sha256,
1412233294Sstas    evp_md_verify_signature,
1413233294Sstas    evp_md_create_signature,
1414233294Sstas    0
1415178825Sdfr};
1416178825Sdfr
1417178825Sdfrstatic const struct signature_alg sha1_alg = {
1418178825Sdfr    "sha1",
1419233294Sstas    ASN1_OID_ID_SECSIG_SHA_1,
1420233294Sstas    &_hx509_signature_sha1_data,
1421178825Sdfr    NULL,
1422178825Sdfr    NULL,
1423178825Sdfr    SIG_DIGEST,
1424233294Sstas    0,
1425233294Sstas    EVP_sha1,
1426233294Sstas    evp_md_verify_signature,
1427233294Sstas    evp_md_create_signature,
1428233294Sstas    0
1429178825Sdfr};
1430178825Sdfr
1431178825Sdfrstatic const struct signature_alg md5_alg = {
1432178825Sdfr    "rsa-md5",
1433233294Sstas    ASN1_OID_ID_RSA_DIGEST_MD5,
1434233294Sstas    &_hx509_signature_md5_data,
1435178825Sdfr    NULL,
1436178825Sdfr    NULL,
1437178825Sdfr    SIG_DIGEST,
1438233294Sstas    0,
1439233294Sstas    EVP_md5,
1440233294Sstas    evp_md_verify_signature,
1441178825Sdfr    NULL,
1442233294Sstas    0
1443178825Sdfr};
1444178825Sdfr
1445233294Sstas/*
1446178825Sdfr * Order matter in this structure, "best" first for each "key
1447233294Sstas * compatible" type (type is ECDSA, RSA, DSA, none, etc)
1448178825Sdfr */
1449178825Sdfr
1450178825Sdfrstatic const struct signature_alg *sig_algs[] = {
1451233294Sstas#ifdef HAVE_OPENSSL
1452233294Sstas    &ecdsa_with_sha256_alg,
1453233294Sstas    &ecdsa_with_sha1_alg,
1454233294Sstas#endif
1455233294Sstas    &rsa_with_sha512_alg,
1456233294Sstas    &rsa_with_sha384_alg,
1457178825Sdfr    &rsa_with_sha256_alg,
1458178825Sdfr    &rsa_with_sha1_alg,
1459233294Sstas    &rsa_with_sha1_alg_secsig,
1460178825Sdfr    &pkcs1_rsa_sha1_alg,
1461178825Sdfr    &rsa_with_md5_alg,
1462178825Sdfr    &heim_rsa_pkcs1_x509,
1463178825Sdfr    &dsa_sha1_alg,
1464233294Sstas    &sha512_alg,
1465233294Sstas    &sha384_alg,
1466178825Sdfr    &sha256_alg,
1467178825Sdfr    &sha1_alg,
1468178825Sdfr    &md5_alg,
1469178825Sdfr    NULL
1470178825Sdfr};
1471178825Sdfr
1472178825Sdfrstatic const struct signature_alg *
1473178825Sdfrfind_sig_alg(const heim_oid *oid)
1474178825Sdfr{
1475233294Sstas    unsigned int i;
1476178825Sdfr    for (i = 0; sig_algs[i]; i++)
1477233294Sstas	if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0)
1478178825Sdfr	    return sig_algs[i];
1479178825Sdfr    return NULL;
1480178825Sdfr}
1481178825Sdfr
1482233294Sstasstatic const AlgorithmIdentifier *
1483233294Sstasalg_for_privatekey(const hx509_private_key pk, int type)
1484233294Sstas{
1485233294Sstas    const heim_oid *keytype;
1486233294Sstas    unsigned int i;
1487233294Sstas
1488233294Sstas    if (pk->ops == NULL)
1489233294Sstas	return NULL;
1490233294Sstas
1491233294Sstas    keytype = pk->ops->key_oid;
1492233294Sstas
1493233294Sstas    for (i = 0; sig_algs[i]; i++) {
1494233294Sstas	if (sig_algs[i]->key_oid == NULL)
1495233294Sstas	    continue;
1496233294Sstas	if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0)
1497233294Sstas	    continue;
1498233294Sstas	if (pk->ops->available &&
1499233294Sstas	    pk->ops->available(pk, sig_algs[i]->sig_alg) == 0)
1500233294Sstas	    continue;
1501233294Sstas	if (type == HX509_SELECT_PUBLIC_SIG)
1502233294Sstas	    return sig_algs[i]->sig_alg;
1503233294Sstas	if (type == HX509_SELECT_DIGEST)
1504233294Sstas	    return sig_algs[i]->digest_alg;
1505233294Sstas
1506233294Sstas	return NULL;
1507233294Sstas    }
1508233294Sstas    return NULL;
1509233294Sstas}
1510233294Sstas
1511178825Sdfr/*
1512178825Sdfr *
1513178825Sdfr */
1514178825Sdfr
1515178825Sdfrstatic struct hx509_private_key_ops *private_algs[] = {
1516178825Sdfr    &rsa_private_key_ops,
1517233294Sstas#ifdef HAVE_OPENSSL
1518233294Sstas    &ecdsa_private_key_ops,
1519233294Sstas#endif
1520178825Sdfr    NULL
1521178825Sdfr};
1522178825Sdfr
1523233294Sstashx509_private_key_ops *
1524233294Sstashx509_find_private_alg(const heim_oid *oid)
1525178825Sdfr{
1526178825Sdfr    int i;
1527178825Sdfr    for (i = 0; private_algs[i]; i++) {
1528178825Sdfr	if (private_algs[i]->key_oid == NULL)
1529178825Sdfr	    continue;
1530233294Sstas	if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0)
1531178825Sdfr	    return private_algs[i];
1532178825Sdfr    }
1533178825Sdfr    return NULL;
1534178825Sdfr}
1535178825Sdfr
1536233294Sstas/*
1537233294Sstas * Check if the algorithm `alg' have a best before date, and if it
1538233294Sstas * des, make sure the its before the time `t'.
1539233294Sstas */
1540178825Sdfr
1541178825Sdfrint
1542233294Sstas_hx509_signature_best_before(hx509_context context,
1543233294Sstas			     const AlgorithmIdentifier *alg,
1544233294Sstas			     time_t t)
1545233294Sstas{
1546233294Sstas    const struct signature_alg *md;
1547233294Sstas
1548233294Sstas    md = find_sig_alg(&alg->algorithm);
1549233294Sstas    if (md == NULL) {
1550233294Sstas	hx509_clear_error_string(context);
1551233294Sstas	return HX509_SIG_ALG_NO_SUPPORTED;
1552233294Sstas    }
1553233294Sstas    if (md->best_before && md->best_before < t) {
1554233294Sstas	hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
1555233294Sstas			       "Algorithm %s has passed it best before date",
1556233294Sstas			       md->name);
1557233294Sstas	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
1558233294Sstas    }
1559233294Sstas    return 0;
1560233294Sstas}
1561233294Sstas
1562233294Sstasint
1563233294Sstas_hx509_self_signed_valid(hx509_context context,
1564233294Sstas			 const AlgorithmIdentifier *alg)
1565233294Sstas{
1566233294Sstas    const struct signature_alg *md;
1567233294Sstas
1568233294Sstas    md = find_sig_alg(&alg->algorithm);
1569233294Sstas    if (md == NULL) {
1570233294Sstas	hx509_clear_error_string(context);
1571233294Sstas	return HX509_SIG_ALG_NO_SUPPORTED;
1572233294Sstas    }
1573233294Sstas    if ((md->flags & SELF_SIGNED_OK) == 0) {
1574233294Sstas	hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
1575233294Sstas			       "Algorithm %s not trusted for self signatures",
1576233294Sstas			       md->name);
1577233294Sstas	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
1578233294Sstas    }
1579233294Sstas    return 0;
1580233294Sstas}
1581233294Sstas
1582233294Sstas
1583233294Sstasint
1584178825Sdfr_hx509_verify_signature(hx509_context context,
1585233294Sstas			const hx509_cert cert,
1586178825Sdfr			const AlgorithmIdentifier *alg,
1587178825Sdfr			const heim_octet_string *data,
1588178825Sdfr			const heim_octet_string *sig)
1589178825Sdfr{
1590178825Sdfr    const struct signature_alg *md;
1591233294Sstas    const Certificate *signer = NULL;
1592178825Sdfr
1593233294Sstas    if (cert)
1594233294Sstas	signer = _hx509_get_cert(cert);
1595233294Sstas
1596178825Sdfr    md = find_sig_alg(&alg->algorithm);
1597178825Sdfr    if (md == NULL) {
1598178825Sdfr	hx509_clear_error_string(context);
1599178825Sdfr	return HX509_SIG_ALG_NO_SUPPORTED;
1600178825Sdfr    }
1601178825Sdfr    if (signer && (md->flags & PROVIDE_CONF) == 0) {
1602178825Sdfr	hx509_clear_error_string(context);
1603178825Sdfr	return HX509_CRYPTO_SIG_NO_CONF;
1604178825Sdfr    }
1605178825Sdfr    if (signer == NULL && (md->flags & REQUIRE_SIGNER)) {
1606178825Sdfr	    hx509_clear_error_string(context);
1607178825Sdfr	return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER;
1608178825Sdfr    }
1609178825Sdfr    if (md->key_oid && signer) {
1610178825Sdfr	const SubjectPublicKeyInfo *spi;
1611178825Sdfr	spi = &signer->tbsCertificate.subjectPublicKeyInfo;
1612178825Sdfr
1613233294Sstas	if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) {
1614178825Sdfr	    hx509_clear_error_string(context);
1615178825Sdfr	    return HX509_SIG_ALG_DONT_MATCH_KEY_ALG;
1616178825Sdfr	}
1617178825Sdfr    }
1618178825Sdfr    return (*md->verify_signature)(context, md, signer, alg, data, sig);
1619178825Sdfr}
1620178825Sdfr
1621178825Sdfrint
1622178825Sdfr_hx509_create_signature(hx509_context context,
1623178825Sdfr			const hx509_private_key signer,
1624178825Sdfr			const AlgorithmIdentifier *alg,
1625178825Sdfr			const heim_octet_string *data,
1626178825Sdfr			AlgorithmIdentifier *signatureAlgorithm,
1627178825Sdfr			heim_octet_string *sig)
1628178825Sdfr{
1629178825Sdfr    const struct signature_alg *md;
1630178825Sdfr
1631178825Sdfr    md = find_sig_alg(&alg->algorithm);
1632178825Sdfr    if (md == NULL) {
1633178825Sdfr	hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
1634178825Sdfr	    "algorithm no supported");
1635178825Sdfr	return HX509_SIG_ALG_NO_SUPPORTED;
1636178825Sdfr    }
1637178825Sdfr
1638178825Sdfr    if (signer && (md->flags & PROVIDE_CONF) == 0) {
1639178825Sdfr	hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
1640178825Sdfr	    "algorithm provides no conf");
1641178825Sdfr	return HX509_CRYPTO_SIG_NO_CONF;
1642178825Sdfr    }
1643178825Sdfr
1644233294Sstas    return (*md->create_signature)(context, md, signer, alg, data,
1645178825Sdfr				   signatureAlgorithm, sig);
1646178825Sdfr}
1647178825Sdfr
1648178825Sdfrint
1649178825Sdfr_hx509_create_signature_bitstring(hx509_context context,
1650178825Sdfr				  const hx509_private_key signer,
1651178825Sdfr				  const AlgorithmIdentifier *alg,
1652178825Sdfr				  const heim_octet_string *data,
1653178825Sdfr				  AlgorithmIdentifier *signatureAlgorithm,
1654178825Sdfr				  heim_bit_string *sig)
1655178825Sdfr{
1656178825Sdfr    heim_octet_string os;
1657178825Sdfr    int ret;
1658178825Sdfr
1659178825Sdfr    ret = _hx509_create_signature(context, signer, alg,
1660178825Sdfr				  data, signatureAlgorithm, &os);
1661178825Sdfr    if (ret)
1662178825Sdfr	return ret;
1663178825Sdfr    sig->data = os.data;
1664178825Sdfr    sig->length = os.length * 8;
1665178825Sdfr    return 0;
1666178825Sdfr}
1667178825Sdfr
1668178825Sdfrint
1669178825Sdfr_hx509_public_encrypt(hx509_context context,
1670178825Sdfr		      const heim_octet_string *cleartext,
1671178825Sdfr		      const Certificate *cert,
1672178825Sdfr		      heim_oid *encryption_oid,
1673178825Sdfr		      heim_octet_string *ciphertext)
1674178825Sdfr{
1675178825Sdfr    const SubjectPublicKeyInfo *spi;
1676178825Sdfr    unsigned char *to;
1677178825Sdfr    int tosize;
1678178825Sdfr    int ret;
1679178825Sdfr    RSA *rsa;
1680178825Sdfr    size_t size;
1681233294Sstas    const unsigned char *p;
1682178825Sdfr
1683178825Sdfr    ciphertext->data = NULL;
1684178825Sdfr    ciphertext->length = 0;
1685178825Sdfr
1686178825Sdfr    spi = &cert->tbsCertificate.subjectPublicKeyInfo;
1687178825Sdfr
1688233294Sstas    p = spi->subjectPublicKey.data;
1689233294Sstas    size = spi->subjectPublicKey.length / 8;
1690233294Sstas
1691233294Sstas    rsa = d2i_RSAPublicKey(NULL, &p, size);
1692178825Sdfr    if (rsa == NULL) {
1693178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1694178825Sdfr	return ENOMEM;
1695178825Sdfr    }
1696178825Sdfr
1697178825Sdfr    tosize = RSA_size(rsa);
1698178825Sdfr    to = malloc(tosize);
1699178825Sdfr    if (to == NULL) {
1700178825Sdfr	RSA_free(rsa);
1701178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1702178825Sdfr	return ENOMEM;
1703178825Sdfr    }
1704178825Sdfr
1705233294Sstas    ret = RSA_public_encrypt(cleartext->length,
1706233294Sstas			     (unsigned char *)cleartext->data,
1707178825Sdfr			     to, rsa, RSA_PKCS1_PADDING);
1708178825Sdfr    RSA_free(rsa);
1709178825Sdfr    if (ret <= 0) {
1710178825Sdfr	free(to);
1711178825Sdfr	hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT,
1712178825Sdfr			       "RSA public encrypt failed with %d", ret);
1713178825Sdfr	return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT;
1714178825Sdfr    }
1715178825Sdfr    if (ret > tosize)
1716178825Sdfr	_hx509_abort("internal rsa decryption failure: ret > tosize");
1717178825Sdfr
1718178825Sdfr    ciphertext->length = ret;
1719178825Sdfr    ciphertext->data = to;
1720178825Sdfr
1721233294Sstas    ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid);
1722178825Sdfr    if (ret) {
1723178825Sdfr	der_free_octet_string(ciphertext);
1724178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1725178825Sdfr	return ENOMEM;
1726178825Sdfr    }
1727178825Sdfr
1728178825Sdfr    return 0;
1729178825Sdfr}
1730178825Sdfr
1731178825Sdfrint
1732233294Sstashx509_private_key_private_decrypt(hx509_context context,
1733178825Sdfr				   const heim_octet_string *ciphertext,
1734178825Sdfr				   const heim_oid *encryption_oid,
1735178825Sdfr				   hx509_private_key p,
1736178825Sdfr				   heim_octet_string *cleartext)
1737178825Sdfr{
1738178825Sdfr    int ret;
1739178825Sdfr
1740178825Sdfr    cleartext->data = NULL;
1741178825Sdfr    cleartext->length = 0;
1742178825Sdfr
1743178825Sdfr    if (p->private_key.rsa == NULL) {
1744178825Sdfr	hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1745178825Sdfr			       "Private RSA key missing");
1746178825Sdfr	return HX509_PRIVATE_KEY_MISSING;
1747178825Sdfr    }
1748178825Sdfr
1749178825Sdfr    cleartext->length = RSA_size(p->private_key.rsa);
1750178825Sdfr    cleartext->data = malloc(cleartext->length);
1751178825Sdfr    if (cleartext->data == NULL) {
1752178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1753178825Sdfr	return ENOMEM;
1754178825Sdfr    }
1755178825Sdfr    ret = RSA_private_decrypt(ciphertext->length, ciphertext->data,
1756178825Sdfr			      cleartext->data,
1757178825Sdfr			      p->private_key.rsa,
1758178825Sdfr			      RSA_PKCS1_PADDING);
1759178825Sdfr    if (ret <= 0) {
1760178825Sdfr	der_free_octet_string(cleartext);
1761178825Sdfr	hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT,
1762178825Sdfr			       "Failed to decrypt using private key: %d", ret);
1763178825Sdfr	return HX509_CRYPTO_RSA_PRIVATE_DECRYPT;
1764178825Sdfr    }
1765233294Sstas    if (cleartext->length < (size_t)ret)
1766178825Sdfr	_hx509_abort("internal rsa decryption failure: ret > tosize");
1767178825Sdfr
1768178825Sdfr    cleartext->length = ret;
1769178825Sdfr
1770178825Sdfr    return 0;
1771178825Sdfr}
1772178825Sdfr
1773178825Sdfr
1774178825Sdfrint
1775233294Sstashx509_parse_private_key(hx509_context context,
1776233294Sstas			 const AlgorithmIdentifier *keyai,
1777178825Sdfr			 const void *data,
1778178825Sdfr			 size_t len,
1779233294Sstas			 hx509_key_format_t format,
1780178825Sdfr			 hx509_private_key *private_key)
1781178825Sdfr{
1782178825Sdfr    struct hx509_private_key_ops *ops;
1783178825Sdfr    int ret;
1784178825Sdfr
1785178825Sdfr    *private_key = NULL;
1786178825Sdfr
1787233294Sstas    ops = hx509_find_private_alg(&keyai->algorithm);
1788178825Sdfr    if (ops == NULL) {
1789178825Sdfr	hx509_clear_error_string(context);
1790178825Sdfr	return HX509_SIG_ALG_NO_SUPPORTED;
1791178825Sdfr    }
1792178825Sdfr
1793233294Sstas    ret = hx509_private_key_init(private_key, ops, NULL);
1794178825Sdfr    if (ret) {
1795178825Sdfr	hx509_set_error_string(context, 0, ret, "out of memory");
1796178825Sdfr	return ret;
1797178825Sdfr    }
1798178825Sdfr
1799233294Sstas    ret = (*ops->import)(context, keyai, data, len, format, *private_key);
1800178825Sdfr    if (ret)
1801233294Sstas	hx509_private_key_free(private_key);
1802178825Sdfr
1803178825Sdfr    return ret;
1804178825Sdfr}
1805178825Sdfr
1806178825Sdfr/*
1807178825Sdfr *
1808178825Sdfr */
1809178825Sdfr
1810178825Sdfrint
1811233294Sstashx509_private_key2SPKI(hx509_context context,
1812178825Sdfr			hx509_private_key private_key,
1813178825Sdfr			SubjectPublicKeyInfo *spki)
1814178825Sdfr{
1815178825Sdfr    const struct hx509_private_key_ops *ops = private_key->ops;
1816178825Sdfr    if (ops == NULL || ops->get_spki == NULL) {
1817178825Sdfr	hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
1818178825Sdfr			       "Private key have no key2SPKI function");
1819178825Sdfr	return HX509_UNIMPLEMENTED_OPERATION;
1820178825Sdfr    }
1821178825Sdfr    return (*ops->get_spki)(context, private_key, spki);
1822178825Sdfr}
1823178825Sdfr
1824178825Sdfrint
1825178825Sdfr_hx509_generate_private_key_init(hx509_context context,
1826178825Sdfr				 const heim_oid *oid,
1827178825Sdfr				 struct hx509_generate_private_context **ctx)
1828178825Sdfr{
1829178825Sdfr    *ctx = NULL;
1830178825Sdfr
1831233294Sstas    if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) {
1832233294Sstas	hx509_set_error_string(context, 0, EINVAL,
1833178825Sdfr			       "private key not an RSA key");
1834178825Sdfr	return EINVAL;
1835178825Sdfr    }
1836178825Sdfr
1837178825Sdfr    *ctx = calloc(1, sizeof(**ctx));
1838178825Sdfr    if (*ctx == NULL) {
1839178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1840178825Sdfr	return ENOMEM;
1841178825Sdfr    }
1842178825Sdfr    (*ctx)->key_oid = oid;
1843178825Sdfr
1844178825Sdfr    return 0;
1845178825Sdfr}
1846178825Sdfr
1847178825Sdfrint
1848178825Sdfr_hx509_generate_private_key_is_ca(hx509_context context,
1849178825Sdfr				  struct hx509_generate_private_context *ctx)
1850178825Sdfr{
1851178825Sdfr    ctx->isCA = 1;
1852178825Sdfr    return 0;
1853178825Sdfr}
1854178825Sdfr
1855178825Sdfrint
1856178825Sdfr_hx509_generate_private_key_bits(hx509_context context,
1857178825Sdfr				 struct hx509_generate_private_context *ctx,
1858178825Sdfr				 unsigned long bits)
1859178825Sdfr{
1860178825Sdfr    ctx->num_bits = bits;
1861178825Sdfr    return 0;
1862178825Sdfr}
1863178825Sdfr
1864178825Sdfr
1865178825Sdfrvoid
1866178825Sdfr_hx509_generate_private_key_free(struct hx509_generate_private_context **ctx)
1867178825Sdfr{
1868178825Sdfr    free(*ctx);
1869178825Sdfr    *ctx = NULL;
1870178825Sdfr}
1871178825Sdfr
1872178825Sdfrint
1873178825Sdfr_hx509_generate_private_key(hx509_context context,
1874178825Sdfr			    struct hx509_generate_private_context *ctx,
1875178825Sdfr			    hx509_private_key *private_key)
1876178825Sdfr{
1877178825Sdfr    struct hx509_private_key_ops *ops;
1878178825Sdfr    int ret;
1879178825Sdfr
1880178825Sdfr    *private_key = NULL;
1881178825Sdfr
1882233294Sstas    ops = hx509_find_private_alg(ctx->key_oid);
1883178825Sdfr    if (ops == NULL) {
1884178825Sdfr	hx509_clear_error_string(context);
1885178825Sdfr	return HX509_SIG_ALG_NO_SUPPORTED;
1886178825Sdfr    }
1887178825Sdfr
1888233294Sstas    ret = hx509_private_key_init(private_key, ops, NULL);
1889178825Sdfr    if (ret) {
1890178825Sdfr	hx509_set_error_string(context, 0, ret, "out of memory");
1891178825Sdfr	return ret;
1892178825Sdfr    }
1893178825Sdfr
1894178825Sdfr    ret = (*ops->generate_private_key)(context, ctx, *private_key);
1895178825Sdfr    if (ret)
1896233294Sstas	hx509_private_key_free(private_key);
1897178825Sdfr
1898178825Sdfr    return ret;
1899178825Sdfr}
1900178825Sdfr
1901178825Sdfr/*
1902178825Sdfr *
1903178825Sdfr */
1904178825Sdfr
1905178825Sdfrconst AlgorithmIdentifier *
1906178825Sdfrhx509_signature_sha512(void)
1907178825Sdfr{ return &_hx509_signature_sha512_data; }
1908178825Sdfr
1909178825Sdfrconst AlgorithmIdentifier *
1910178825Sdfrhx509_signature_sha384(void)
1911178825Sdfr{ return &_hx509_signature_sha384_data; }
1912178825Sdfr
1913178825Sdfrconst AlgorithmIdentifier *
1914178825Sdfrhx509_signature_sha256(void)
1915178825Sdfr{ return &_hx509_signature_sha256_data; }
1916178825Sdfr
1917178825Sdfrconst AlgorithmIdentifier *
1918178825Sdfrhx509_signature_sha1(void)
1919178825Sdfr{ return &_hx509_signature_sha1_data; }
1920178825Sdfr
1921178825Sdfrconst AlgorithmIdentifier *
1922178825Sdfrhx509_signature_md5(void)
1923178825Sdfr{ return &_hx509_signature_md5_data; }
1924178825Sdfr
1925178825Sdfrconst AlgorithmIdentifier *
1926233294Sstashx509_signature_ecPublicKey(void)
1927233294Sstas{ return &_hx509_signature_ecPublicKey; }
1928178825Sdfr
1929178825Sdfrconst AlgorithmIdentifier *
1930233294Sstashx509_signature_ecdsa_with_sha256(void)
1931233294Sstas{ return &_hx509_signature_ecdsa_with_sha256_data; }
1932233294Sstas
1933233294Sstasconst AlgorithmIdentifier *
1934233294Sstashx509_signature_ecdsa_with_sha1(void)
1935233294Sstas{ return &_hx509_signature_ecdsa_with_sha1_data; }
1936233294Sstas
1937233294Sstasconst AlgorithmIdentifier *
1938178825Sdfrhx509_signature_rsa_with_sha512(void)
1939178825Sdfr{ return &_hx509_signature_rsa_with_sha512_data; }
1940178825Sdfr
1941178825Sdfrconst AlgorithmIdentifier *
1942178825Sdfrhx509_signature_rsa_with_sha384(void)
1943178825Sdfr{ return &_hx509_signature_rsa_with_sha384_data; }
1944178825Sdfr
1945178825Sdfrconst AlgorithmIdentifier *
1946178825Sdfrhx509_signature_rsa_with_sha256(void)
1947178825Sdfr{ return &_hx509_signature_rsa_with_sha256_data; }
1948178825Sdfr
1949178825Sdfrconst AlgorithmIdentifier *
1950178825Sdfrhx509_signature_rsa_with_sha1(void)
1951178825Sdfr{ return &_hx509_signature_rsa_with_sha1_data; }
1952178825Sdfr
1953178825Sdfrconst AlgorithmIdentifier *
1954178825Sdfrhx509_signature_rsa_with_md5(void)
1955178825Sdfr{ return &_hx509_signature_rsa_with_md5_data; }
1956178825Sdfr
1957178825Sdfrconst AlgorithmIdentifier *
1958178825Sdfrhx509_signature_rsa(void)
1959178825Sdfr{ return &_hx509_signature_rsa_data; }
1960178825Sdfr
1961178825Sdfrconst AlgorithmIdentifier *
1962178825Sdfrhx509_signature_rsa_pkcs1_x509(void)
1963178825Sdfr{ return &_hx509_signature_rsa_pkcs1_x509_data; }
1964178825Sdfr
1965178825Sdfrconst AlgorithmIdentifier *
1966178825Sdfrhx509_crypto_des_rsdi_ede3_cbc(void)
1967178825Sdfr{ return &_hx509_des_rsdi_ede3_cbc_oid; }
1968178825Sdfr
1969178825Sdfrconst AlgorithmIdentifier *
1970178825Sdfrhx509_crypto_aes128_cbc(void)
1971178825Sdfr{ return &_hx509_crypto_aes128_cbc_data; }
1972178825Sdfr
1973178825Sdfrconst AlgorithmIdentifier *
1974178825Sdfrhx509_crypto_aes256_cbc(void)
1975178825Sdfr{ return &_hx509_crypto_aes256_cbc_data; }
1976178825Sdfr
1977178825Sdfr/*
1978178825Sdfr *
1979178825Sdfr */
1980178825Sdfr
1981233294Sstasconst AlgorithmIdentifier * _hx509_crypto_default_sig_alg =
1982233294Sstas    &_hx509_signature_rsa_with_sha256_data;
1983233294Sstasconst AlgorithmIdentifier * _hx509_crypto_default_digest_alg =
1984233294Sstas    &_hx509_signature_sha256_data;
1985233294Sstasconst AlgorithmIdentifier * _hx509_crypto_default_secret_alg =
1986178825Sdfr    &_hx509_crypto_aes128_cbc_data;
1987178825Sdfr
1988178825Sdfr/*
1989178825Sdfr *
1990178825Sdfr */
1991178825Sdfr
1992178825Sdfrint
1993233294Sstashx509_private_key_init(hx509_private_key *key,
1994178825Sdfr			hx509_private_key_ops *ops,
1995178825Sdfr			void *keydata)
1996178825Sdfr{
1997178825Sdfr    *key = calloc(1, sizeof(**key));
1998178825Sdfr    if (*key == NULL)
1999178825Sdfr	return ENOMEM;
2000178825Sdfr    (*key)->ref = 1;
2001178825Sdfr    (*key)->ops = ops;
2002178825Sdfr    (*key)->private_key.keydata = keydata;
2003178825Sdfr    return 0;
2004178825Sdfr}
2005178825Sdfr
2006178825Sdfrhx509_private_key
2007178825Sdfr_hx509_private_key_ref(hx509_private_key key)
2008178825Sdfr{
2009233294Sstas    if (key->ref == 0)
2010233294Sstas	_hx509_abort("key refcount <= 0 on ref");
2011178825Sdfr    key->ref++;
2012233294Sstas    if (key->ref == UINT_MAX)
2013233294Sstas	_hx509_abort("key refcount == UINT_MAX on ref");
2014178825Sdfr    return key;
2015178825Sdfr}
2016178825Sdfr
2017178825Sdfrconst char *
2018178825Sdfr_hx509_private_pem_name(hx509_private_key key)
2019178825Sdfr{
2020178825Sdfr    return key->ops->pemtype;
2021178825Sdfr}
2022178825Sdfr
2023178825Sdfrint
2024233294Sstashx509_private_key_free(hx509_private_key *key)
2025178825Sdfr{
2026178825Sdfr    if (key == NULL || *key == NULL)
2027178825Sdfr	return 0;
2028178825Sdfr
2029233294Sstas    if ((*key)->ref == 0)
2030233294Sstas	_hx509_abort("key refcount == 0 on free");
2031178825Sdfr    if (--(*key)->ref > 0)
2032178825Sdfr	return 0;
2033178825Sdfr
2034233294Sstas    if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
2035233294Sstas	if ((*key)->private_key.rsa)
2036233294Sstas	    RSA_free((*key)->private_key.rsa);
2037233294Sstas#ifdef HAVE_OPENSSL
2038233294Sstas    } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) {
2039233294Sstas	if ((*key)->private_key.ecdsa)
2040233294Sstas	    EC_KEY_free((*key)->private_key.ecdsa);
2041233294Sstas#endif
2042233294Sstas    }
2043178825Sdfr    (*key)->private_key.rsa = NULL;
2044178825Sdfr    free(*key);
2045178825Sdfr    *key = NULL;
2046178825Sdfr    return 0;
2047178825Sdfr}
2048178825Sdfr
2049178825Sdfrvoid
2050233294Sstashx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
2051178825Sdfr{
2052178825Sdfr    if (key->private_key.rsa)
2053178825Sdfr	RSA_free(key->private_key.rsa);
2054178825Sdfr    key->private_key.rsa = ptr;
2055233294Sstas    key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
2056178825Sdfr    key->md = &pkcs1_rsa_sha1_alg;
2057178825Sdfr}
2058178825Sdfr
2059233294Sstasint
2060178825Sdfr_hx509_private_key_oid(hx509_context context,
2061178825Sdfr		       const hx509_private_key key,
2062178825Sdfr		       heim_oid *data)
2063178825Sdfr{
2064178825Sdfr    int ret;
2065233294Sstas    ret = der_copy_oid(key->ops->key_oid, data);
2066178825Sdfr    if (ret)
2067178825Sdfr	hx509_set_error_string(context, 0, ret, "malloc out of memory");
2068178825Sdfr    return ret;
2069178825Sdfr}
2070178825Sdfr
2071178825Sdfrint
2072178825Sdfr_hx509_private_key_exportable(hx509_private_key key)
2073178825Sdfr{
2074178825Sdfr    if (key->ops->export == NULL)
2075178825Sdfr	return 0;
2076178825Sdfr    return 1;
2077178825Sdfr}
2078178825Sdfr
2079178825SdfrBIGNUM *
2080178825Sdfr_hx509_private_key_get_internal(hx509_context context,
2081233294Sstas				hx509_private_key key,
2082178825Sdfr				const char *type)
2083178825Sdfr{
2084178825Sdfr    if (key->ops->get_internal == NULL)
2085178825Sdfr	return NULL;
2086178825Sdfr    return (*key->ops->get_internal)(context, key, type);
2087178825Sdfr}
2088178825Sdfr
2089233294Sstasint
2090178825Sdfr_hx509_private_key_export(hx509_context context,
2091178825Sdfr			  const hx509_private_key key,
2092233294Sstas			  hx509_key_format_t format,
2093178825Sdfr			  heim_octet_string *data)
2094178825Sdfr{
2095178825Sdfr    if (key->ops->export == NULL) {
2096178825Sdfr	hx509_clear_error_string(context);
2097178825Sdfr	return HX509_UNIMPLEMENTED_OPERATION;
2098178825Sdfr    }
2099233294Sstas    return (*key->ops->export)(context, key, format, data);
2100178825Sdfr}
2101178825Sdfr
2102178825Sdfr/*
2103178825Sdfr *
2104178825Sdfr */
2105178825Sdfr
2106178825Sdfrstruct hx509cipher {
2107178825Sdfr    const char *name;
2108233294Sstas    int flags;
2109233294Sstas#define CIPHER_WEAK 1
2110233294Sstas    const heim_oid *oid;
2111178825Sdfr    const AlgorithmIdentifier *(*ai_func)(void);
2112178825Sdfr    const EVP_CIPHER *(*evp_func)(void);
2113178825Sdfr    int (*get_params)(hx509_context, const hx509_crypto,
2114178825Sdfr		      const heim_octet_string *, heim_octet_string *);
2115233294Sstas    int (*set_params)(hx509_context, const heim_octet_string *,
2116178825Sdfr		      hx509_crypto, heim_octet_string *);
2117178825Sdfr};
2118178825Sdfr
2119178825Sdfrstruct hx509_crypto_data {
2120178825Sdfr    char *name;
2121233294Sstas    int flags;
2122233294Sstas#define ALLOW_WEAK 	1
2123233294Sstas
2124233294Sstas#define PADDING_NONE	2
2125233294Sstas#define PADDING_PKCS7	4
2126233294Sstas#define PADDING_FLAGS	(2|4)
2127178825Sdfr    const struct hx509cipher *cipher;
2128178825Sdfr    const EVP_CIPHER *c;
2129178825Sdfr    heim_octet_string key;
2130178825Sdfr    heim_oid oid;
2131178825Sdfr    void *param;
2132178825Sdfr};
2133178825Sdfr
2134178825Sdfr/*
2135178825Sdfr *
2136178825Sdfr */
2137178825Sdfr
2138233294Sstasstatic unsigned private_rc2_40_oid_data[] = { 127, 1 };
2139178825Sdfr
2140233294Sstasstatic heim_oid asn1_oid_private_rc2_40 =
2141233294Sstas    { 2, private_rc2_40_oid_data };
2142178825Sdfr
2143178825Sdfr/*
2144178825Sdfr *
2145178825Sdfr */
2146178825Sdfr
2147178825Sdfrstatic int
2148178825SdfrCMSCBCParam_get(hx509_context context, const hx509_crypto crypto,
2149178825Sdfr		 const heim_octet_string *ivec, heim_octet_string *param)
2150178825Sdfr{
2151178825Sdfr    size_t size;
2152178825Sdfr    int ret;
2153178825Sdfr
2154178825Sdfr    assert(crypto->param == NULL);
2155178825Sdfr    if (ivec == NULL)
2156178825Sdfr	return 0;
2157178825Sdfr
2158178825Sdfr    ASN1_MALLOC_ENCODE(CMSCBCParameter, param->data, param->length,
2159178825Sdfr		       ivec, &size, ret);
2160178825Sdfr    if (ret == 0 && size != param->length)
2161178825Sdfr	_hx509_abort("Internal asn1 encoder failure");
2162178825Sdfr    if (ret)
2163178825Sdfr	hx509_clear_error_string(context);
2164178825Sdfr    return ret;
2165178825Sdfr}
2166178825Sdfr
2167178825Sdfrstatic int
2168178825SdfrCMSCBCParam_set(hx509_context context, const heim_octet_string *param,
2169178825Sdfr		hx509_crypto crypto, heim_octet_string *ivec)
2170178825Sdfr{
2171178825Sdfr    int ret;
2172178825Sdfr    if (ivec == NULL)
2173178825Sdfr	return 0;
2174178825Sdfr
2175178825Sdfr    ret = decode_CMSCBCParameter(param->data, param->length, ivec, NULL);
2176178825Sdfr    if (ret)
2177178825Sdfr	hx509_clear_error_string(context);
2178178825Sdfr
2179178825Sdfr    return ret;
2180178825Sdfr}
2181178825Sdfr
2182178825Sdfrstruct _RC2_params {
2183178825Sdfr    int maximum_effective_key;
2184178825Sdfr};
2185178825Sdfr
2186178825Sdfrstatic int
2187178825SdfrCMSRC2CBCParam_get(hx509_context context, const hx509_crypto crypto,
2188178825Sdfr		   const heim_octet_string *ivec, heim_octet_string *param)
2189178825Sdfr{
2190178825Sdfr    CMSRC2CBCParameter rc2params;
2191178825Sdfr    const struct _RC2_params *p = crypto->param;
2192178825Sdfr    int maximum_effective_key = 128;
2193178825Sdfr    size_t size;
2194178825Sdfr    int ret;
2195178825Sdfr
2196178825Sdfr    memset(&rc2params, 0, sizeof(rc2params));
2197178825Sdfr
2198178825Sdfr    if (p)
2199178825Sdfr	maximum_effective_key = p->maximum_effective_key;
2200178825Sdfr
2201178825Sdfr    switch(maximum_effective_key) {
2202178825Sdfr    case 40:
2203178825Sdfr	rc2params.rc2ParameterVersion = 160;
2204178825Sdfr	break;
2205178825Sdfr    case 64:
2206178825Sdfr	rc2params.rc2ParameterVersion = 120;
2207178825Sdfr	break;
2208178825Sdfr    case 128:
2209178825Sdfr	rc2params.rc2ParameterVersion = 58;
2210178825Sdfr	break;
2211178825Sdfr    }
2212178825Sdfr    rc2params.iv = *ivec;
2213178825Sdfr
2214178825Sdfr    ASN1_MALLOC_ENCODE(CMSRC2CBCParameter, param->data, param->length,
2215178825Sdfr		       &rc2params, &size, ret);
2216178825Sdfr    if (ret == 0 && size != param->length)
2217178825Sdfr	_hx509_abort("Internal asn1 encoder failure");
2218178825Sdfr
2219178825Sdfr    return ret;
2220178825Sdfr}
2221178825Sdfr
2222178825Sdfrstatic int
2223178825SdfrCMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
2224178825Sdfr		   hx509_crypto crypto, heim_octet_string *ivec)
2225178825Sdfr{
2226178825Sdfr    CMSRC2CBCParameter rc2param;
2227178825Sdfr    struct _RC2_params *p;
2228178825Sdfr    size_t size;
2229178825Sdfr    int ret;
2230178825Sdfr
2231178825Sdfr    ret = decode_CMSRC2CBCParameter(param->data, param->length,
2232178825Sdfr				    &rc2param, &size);
2233178825Sdfr    if (ret) {
2234178825Sdfr	hx509_clear_error_string(context);
2235178825Sdfr	return ret;
2236178825Sdfr    }
2237178825Sdfr
2238178825Sdfr    p = calloc(1, sizeof(*p));
2239178825Sdfr    if (p == NULL) {
2240178825Sdfr	free_CMSRC2CBCParameter(&rc2param);
2241178825Sdfr	hx509_clear_error_string(context);
2242178825Sdfr	return ENOMEM;
2243178825Sdfr    }
2244178825Sdfr    switch(rc2param.rc2ParameterVersion) {
2245178825Sdfr    case 160:
2246178825Sdfr	crypto->c = EVP_rc2_40_cbc();
2247178825Sdfr	p->maximum_effective_key = 40;
2248178825Sdfr	break;
2249178825Sdfr    case 120:
2250178825Sdfr	crypto->c = EVP_rc2_64_cbc();
2251178825Sdfr	p->maximum_effective_key = 64;
2252178825Sdfr	break;
2253178825Sdfr    case 58:
2254178825Sdfr	crypto->c = EVP_rc2_cbc();
2255178825Sdfr	p->maximum_effective_key = 128;
2256178825Sdfr	break;
2257178825Sdfr    default:
2258178825Sdfr	free(p);
2259178825Sdfr	free_CMSRC2CBCParameter(&rc2param);
2260178825Sdfr	return HX509_CRYPTO_SIG_INVALID_FORMAT;
2261178825Sdfr    }
2262178825Sdfr    if (ivec)
2263178825Sdfr	ret = der_copy_octet_string(&rc2param.iv, ivec);
2264178825Sdfr    free_CMSRC2CBCParameter(&rc2param);
2265178825Sdfr    if (ret) {
2266178825Sdfr	free(p);
2267178825Sdfr	hx509_clear_error_string(context);
2268178825Sdfr    } else
2269178825Sdfr	crypto->param = p;
2270178825Sdfr
2271178825Sdfr    return ret;
2272178825Sdfr}
2273178825Sdfr
2274178825Sdfr/*
2275178825Sdfr *
2276178825Sdfr */
2277178825Sdfr
2278178825Sdfrstatic const struct hx509cipher ciphers[] = {
2279178825Sdfr    {
2280178825Sdfr	"rc2-cbc",
2281233294Sstas	CIPHER_WEAK,
2282233294Sstas	ASN1_OID_ID_PKCS3_RC2_CBC,
2283178825Sdfr	NULL,
2284178825Sdfr	EVP_rc2_cbc,
2285178825Sdfr	CMSRC2CBCParam_get,
2286178825Sdfr	CMSRC2CBCParam_set
2287178825Sdfr    },
2288178825Sdfr    {
2289178825Sdfr	"rc2-cbc",
2290233294Sstas	CIPHER_WEAK,
2291233294Sstas	ASN1_OID_ID_RSADSI_RC2_CBC,
2292178825Sdfr	NULL,
2293178825Sdfr	EVP_rc2_cbc,
2294178825Sdfr	CMSRC2CBCParam_get,
2295178825Sdfr	CMSRC2CBCParam_set
2296178825Sdfr    },
2297178825Sdfr    {
2298178825Sdfr	"rc2-40-cbc",
2299233294Sstas	CIPHER_WEAK,
2300233294Sstas	&asn1_oid_private_rc2_40,
2301178825Sdfr	NULL,
2302178825Sdfr	EVP_rc2_40_cbc,
2303178825Sdfr	CMSRC2CBCParam_get,
2304178825Sdfr	CMSRC2CBCParam_set
2305178825Sdfr    },
2306178825Sdfr    {
2307178825Sdfr	"des-ede3-cbc",
2308233294Sstas	0,
2309233294Sstas	ASN1_OID_ID_PKCS3_DES_EDE3_CBC,
2310178825Sdfr	NULL,
2311178825Sdfr	EVP_des_ede3_cbc,
2312178825Sdfr	CMSCBCParam_get,
2313178825Sdfr	CMSCBCParam_set
2314178825Sdfr    },
2315178825Sdfr    {
2316178825Sdfr	"des-ede3-cbc",
2317233294Sstas	0,
2318233294Sstas	ASN1_OID_ID_RSADSI_DES_EDE3_CBC,
2319178825Sdfr	hx509_crypto_des_rsdi_ede3_cbc,
2320178825Sdfr	EVP_des_ede3_cbc,
2321178825Sdfr	CMSCBCParam_get,
2322178825Sdfr	CMSCBCParam_set
2323178825Sdfr    },
2324178825Sdfr    {
2325178825Sdfr	"aes-128-cbc",
2326233294Sstas	0,
2327233294Sstas	ASN1_OID_ID_AES_128_CBC,
2328178825Sdfr	hx509_crypto_aes128_cbc,
2329178825Sdfr	EVP_aes_128_cbc,
2330178825Sdfr	CMSCBCParam_get,
2331178825Sdfr	CMSCBCParam_set
2332178825Sdfr    },
2333178825Sdfr    {
2334178825Sdfr	"aes-192-cbc",
2335233294Sstas	0,
2336233294Sstas	ASN1_OID_ID_AES_192_CBC,
2337178825Sdfr	NULL,
2338178825Sdfr	EVP_aes_192_cbc,
2339178825Sdfr	CMSCBCParam_get,
2340178825Sdfr	CMSCBCParam_set
2341178825Sdfr    },
2342178825Sdfr    {
2343178825Sdfr	"aes-256-cbc",
2344233294Sstas	0,
2345233294Sstas	ASN1_OID_ID_AES_256_CBC,
2346178825Sdfr	hx509_crypto_aes256_cbc,
2347178825Sdfr	EVP_aes_256_cbc,
2348178825Sdfr	CMSCBCParam_get,
2349178825Sdfr	CMSCBCParam_set
2350178825Sdfr    }
2351178825Sdfr};
2352178825Sdfr
2353178825Sdfrstatic const struct hx509cipher *
2354178825Sdfrfind_cipher_by_oid(const heim_oid *oid)
2355178825Sdfr{
2356233294Sstas    size_t i;
2357178825Sdfr
2358178825Sdfr    for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
2359233294Sstas	if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0)
2360178825Sdfr	    return &ciphers[i];
2361178825Sdfr
2362178825Sdfr    return NULL;
2363178825Sdfr}
2364178825Sdfr
2365178825Sdfrstatic const struct hx509cipher *
2366178825Sdfrfind_cipher_by_name(const char *name)
2367178825Sdfr{
2368233294Sstas    size_t i;
2369178825Sdfr
2370178825Sdfr    for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
2371178825Sdfr	if (strcasecmp(name, ciphers[i].name) == 0)
2372178825Sdfr	    return &ciphers[i];
2373178825Sdfr
2374178825Sdfr    return NULL;
2375178825Sdfr}
2376178825Sdfr
2377178825Sdfr
2378178825Sdfrconst heim_oid *
2379178825Sdfrhx509_crypto_enctype_by_name(const char *name)
2380178825Sdfr{
2381178825Sdfr    const struct hx509cipher *cipher;
2382178825Sdfr
2383178825Sdfr    cipher = find_cipher_by_name(name);
2384178825Sdfr    if (cipher == NULL)
2385178825Sdfr	return NULL;
2386233294Sstas    return cipher->oid;
2387178825Sdfr}
2388178825Sdfr
2389178825Sdfrint
2390178825Sdfrhx509_crypto_init(hx509_context context,
2391178825Sdfr		  const char *provider,
2392178825Sdfr		  const heim_oid *enctype,
2393178825Sdfr		  hx509_crypto *crypto)
2394178825Sdfr{
2395178825Sdfr    const struct hx509cipher *cipher;
2396178825Sdfr
2397178825Sdfr    *crypto = NULL;
2398178825Sdfr
2399178825Sdfr    cipher = find_cipher_by_oid(enctype);
2400178825Sdfr    if (cipher == NULL) {
2401178825Sdfr	hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
2402178825Sdfr			       "Algorithm not supported");
2403178825Sdfr	return HX509_ALG_NOT_SUPP;
2404178825Sdfr    }
2405178825Sdfr
2406178825Sdfr    *crypto = calloc(1, sizeof(**crypto));
2407178825Sdfr    if (*crypto == NULL) {
2408178825Sdfr	hx509_clear_error_string(context);
2409178825Sdfr	return ENOMEM;
2410178825Sdfr    }
2411178825Sdfr
2412233294Sstas    (*crypto)->flags = PADDING_PKCS7;
2413178825Sdfr    (*crypto)->cipher = cipher;
2414178825Sdfr    (*crypto)->c = (*cipher->evp_func)();
2415178825Sdfr
2416178825Sdfr    if (der_copy_oid(enctype, &(*crypto)->oid)) {
2417178825Sdfr	hx509_crypto_destroy(*crypto);
2418178825Sdfr	*crypto = NULL;
2419178825Sdfr	hx509_clear_error_string(context);
2420178825Sdfr	return ENOMEM;
2421178825Sdfr    }
2422178825Sdfr
2423178825Sdfr    return 0;
2424178825Sdfr}
2425178825Sdfr
2426178825Sdfrconst char *
2427178825Sdfrhx509_crypto_provider(hx509_crypto crypto)
2428178825Sdfr{
2429178825Sdfr    return "unknown";
2430178825Sdfr}
2431178825Sdfr
2432178825Sdfrvoid
2433178825Sdfrhx509_crypto_destroy(hx509_crypto crypto)
2434178825Sdfr{
2435178825Sdfr    if (crypto->name)
2436178825Sdfr	free(crypto->name);
2437178825Sdfr    if (crypto->key.data)
2438178825Sdfr	free(crypto->key.data);
2439178825Sdfr    if (crypto->param)
2440178825Sdfr	free(crypto->param);
2441178825Sdfr    der_free_oid(&crypto->oid);
2442178825Sdfr    memset(crypto, 0, sizeof(*crypto));
2443178825Sdfr    free(crypto);
2444178825Sdfr}
2445178825Sdfr
2446178825Sdfrint
2447178825Sdfrhx509_crypto_set_key_name(hx509_crypto crypto, const char *name)
2448178825Sdfr{
2449178825Sdfr    return 0;
2450178825Sdfr}
2451178825Sdfr
2452233294Sstasvoid
2453233294Sstashx509_crypto_allow_weak(hx509_crypto crypto)
2454233294Sstas{
2455233294Sstas    crypto->flags |= ALLOW_WEAK;
2456233294Sstas}
2457233294Sstas
2458233294Sstasvoid
2459233294Sstashx509_crypto_set_padding(hx509_crypto crypto, int padding_type)
2460233294Sstas{
2461233294Sstas    switch (padding_type) {
2462233294Sstas    case HX509_CRYPTO_PADDING_PKCS7:
2463233294Sstas	crypto->flags &= ~PADDING_FLAGS;
2464233294Sstas	crypto->flags |= PADDING_PKCS7;
2465233294Sstas	break;
2466233294Sstas    case HX509_CRYPTO_PADDING_NONE:
2467233294Sstas	crypto->flags &= ~PADDING_FLAGS;
2468233294Sstas	crypto->flags |= PADDING_NONE;
2469233294Sstas	break;
2470233294Sstas    default:
2471233294Sstas	_hx509_abort("Invalid padding");
2472233294Sstas    }
2473233294Sstas}
2474233294Sstas
2475178825Sdfrint
2476178825Sdfrhx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
2477178825Sdfr{
2478233294Sstas    if (EVP_CIPHER_key_length(crypto->c) > (int)length)
2479178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2480178825Sdfr
2481178825Sdfr    if (crypto->key.data) {
2482178825Sdfr	free(crypto->key.data);
2483178825Sdfr	crypto->key.data = NULL;
2484178825Sdfr	crypto->key.length = 0;
2485178825Sdfr    }
2486178825Sdfr    crypto->key.data = malloc(length);
2487178825Sdfr    if (crypto->key.data == NULL)
2488178825Sdfr	return ENOMEM;
2489178825Sdfr    memcpy(crypto->key.data, data, length);
2490178825Sdfr    crypto->key.length = length;
2491178825Sdfr
2492178825Sdfr    return 0;
2493178825Sdfr}
2494178825Sdfr
2495178825Sdfrint
2496178825Sdfrhx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key)
2497178825Sdfr{
2498178825Sdfr    if (crypto->key.data) {
2499178825Sdfr	free(crypto->key.data);
2500178825Sdfr	crypto->key.length = 0;
2501178825Sdfr    }
2502178825Sdfr
2503178825Sdfr    crypto->key.length = EVP_CIPHER_key_length(crypto->c);
2504178825Sdfr    crypto->key.data = malloc(crypto->key.length);
2505178825Sdfr    if (crypto->key.data == NULL) {
2506178825Sdfr	crypto->key.length = 0;
2507178825Sdfr	return ENOMEM;
2508178825Sdfr    }
2509178825Sdfr    if (RAND_bytes(crypto->key.data, crypto->key.length) <= 0) {
2510178825Sdfr	free(crypto->key.data);
2511178825Sdfr	crypto->key.data = NULL;
2512178825Sdfr	crypto->key.length = 0;
2513178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2514178825Sdfr    }
2515178825Sdfr    if (key)
2516178825Sdfr	return der_copy_octet_string(&crypto->key, key);
2517178825Sdfr    else
2518178825Sdfr	return 0;
2519178825Sdfr}
2520178825Sdfr
2521178825Sdfrint
2522178825Sdfrhx509_crypto_set_params(hx509_context context,
2523233294Sstas			hx509_crypto crypto,
2524178825Sdfr			const heim_octet_string *param,
2525178825Sdfr			heim_octet_string *ivec)
2526178825Sdfr{
2527178825Sdfr    return (*crypto->cipher->set_params)(context, param, crypto, ivec);
2528178825Sdfr}
2529178825Sdfr
2530178825Sdfrint
2531178825Sdfrhx509_crypto_get_params(hx509_context context,
2532233294Sstas			hx509_crypto crypto,
2533178825Sdfr			const heim_octet_string *ivec,
2534178825Sdfr			heim_octet_string *param)
2535178825Sdfr{
2536178825Sdfr    return (*crypto->cipher->get_params)(context, crypto, ivec, param);
2537178825Sdfr}
2538178825Sdfr
2539178825Sdfrint
2540178825Sdfrhx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
2541178825Sdfr{
2542178825Sdfr    ivec->length = EVP_CIPHER_iv_length(crypto->c);
2543178825Sdfr    ivec->data = malloc(ivec->length);
2544178825Sdfr    if (ivec->data == NULL) {
2545178825Sdfr	ivec->length = 0;
2546178825Sdfr	return ENOMEM;
2547178825Sdfr    }
2548178825Sdfr
2549178825Sdfr    if (RAND_bytes(ivec->data, ivec->length) <= 0) {
2550178825Sdfr	free(ivec->data);
2551178825Sdfr	ivec->data = NULL;
2552178825Sdfr	ivec->length = 0;
2553178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2554178825Sdfr    }
2555178825Sdfr    return 0;
2556178825Sdfr}
2557178825Sdfr
2558178825Sdfrint
2559178825Sdfrhx509_crypto_encrypt(hx509_crypto crypto,
2560178825Sdfr		     const void *data,
2561178825Sdfr		     const size_t length,
2562178825Sdfr		     const heim_octet_string *ivec,
2563178825Sdfr		     heim_octet_string **ciphertext)
2564178825Sdfr{
2565178825Sdfr    EVP_CIPHER_CTX evp;
2566233294Sstas    size_t padsize, bsize;
2567178825Sdfr    int ret;
2568178825Sdfr
2569178825Sdfr    *ciphertext = NULL;
2570178825Sdfr
2571233294Sstas    if ((crypto->cipher->flags & CIPHER_WEAK) &&
2572233294Sstas	(crypto->flags & ALLOW_WEAK) == 0)
2573233294Sstas	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
2574178825Sdfr
2575233294Sstas    assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length);
2576233294Sstas
2577178825Sdfr    EVP_CIPHER_CTX_init(&evp);
2578178825Sdfr
2579178825Sdfr    ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
2580178825Sdfr			    crypto->key.data, ivec->data, 1);
2581178825Sdfr    if (ret != 1) {
2582178825Sdfr	EVP_CIPHER_CTX_cleanup(&evp);
2583178825Sdfr	ret = HX509_CRYPTO_INTERNAL_ERROR;
2584178825Sdfr	goto out;
2585178825Sdfr    }
2586178825Sdfr
2587178825Sdfr    *ciphertext = calloc(1, sizeof(**ciphertext));
2588178825Sdfr    if (*ciphertext == NULL) {
2589178825Sdfr	ret = ENOMEM;
2590178825Sdfr	goto out;
2591178825Sdfr    }
2592233294Sstas
2593233294Sstas    assert(crypto->flags & PADDING_FLAGS);
2594233294Sstas
2595233294Sstas    bsize = EVP_CIPHER_block_size(crypto->c);
2596233294Sstas    padsize = 0;
2597233294Sstas
2598233294Sstas    if (crypto->flags & PADDING_NONE) {
2599233294Sstas	if (bsize != 1 && (length % bsize) != 0)
2600233294Sstas	    return HX509_CMS_PADDING_ERROR;
2601233294Sstas    } else if (crypto->flags & PADDING_PKCS7) {
2602233294Sstas	if (bsize != 1)
2603233294Sstas	    padsize = bsize - (length % bsize);
2604178825Sdfr    }
2605233294Sstas
2606178825Sdfr    (*ciphertext)->length = length + padsize;
2607178825Sdfr    (*ciphertext)->data = malloc(length + padsize);
2608178825Sdfr    if ((*ciphertext)->data == NULL) {
2609178825Sdfr	ret = ENOMEM;
2610178825Sdfr	goto out;
2611178825Sdfr    }
2612233294Sstas
2613178825Sdfr    memcpy((*ciphertext)->data, data, length);
2614178825Sdfr    if (padsize) {
2615233294Sstas	size_t i;
2616178825Sdfr	unsigned char *p = (*ciphertext)->data;
2617178825Sdfr	p += length;
2618178825Sdfr	for (i = 0; i < padsize; i++)
2619178825Sdfr	    *p++ = padsize;
2620178825Sdfr    }
2621178825Sdfr
2622178825Sdfr    ret = EVP_Cipher(&evp, (*ciphertext)->data,
2623178825Sdfr		     (*ciphertext)->data,
2624178825Sdfr		     length + padsize);
2625178825Sdfr    if (ret != 1) {
2626178825Sdfr	ret = HX509_CRYPTO_INTERNAL_ERROR;
2627178825Sdfr	goto out;
2628178825Sdfr    }
2629178825Sdfr    ret = 0;
2630178825Sdfr
2631178825Sdfr out:
2632178825Sdfr    if (ret) {
2633178825Sdfr	if (*ciphertext) {
2634178825Sdfr	    if ((*ciphertext)->data) {
2635178825Sdfr		free((*ciphertext)->data);
2636178825Sdfr	    }
2637178825Sdfr	    free(*ciphertext);
2638178825Sdfr	    *ciphertext = NULL;
2639178825Sdfr	}
2640178825Sdfr    }
2641178825Sdfr    EVP_CIPHER_CTX_cleanup(&evp);
2642178825Sdfr
2643178825Sdfr    return ret;
2644178825Sdfr}
2645178825Sdfr
2646178825Sdfrint
2647178825Sdfrhx509_crypto_decrypt(hx509_crypto crypto,
2648178825Sdfr		     const void *data,
2649178825Sdfr		     const size_t length,
2650178825Sdfr		     heim_octet_string *ivec,
2651178825Sdfr		     heim_octet_string *clear)
2652178825Sdfr{
2653178825Sdfr    EVP_CIPHER_CTX evp;
2654178825Sdfr    void *idata = NULL;
2655178825Sdfr    int ret;
2656178825Sdfr
2657178825Sdfr    clear->data = NULL;
2658178825Sdfr    clear->length = 0;
2659178825Sdfr
2660233294Sstas    if ((crypto->cipher->flags & CIPHER_WEAK) &&
2661233294Sstas	(crypto->flags & ALLOW_WEAK) == 0)
2662233294Sstas	return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
2663233294Sstas
2664233294Sstas    if (ivec && EVP_CIPHER_iv_length(crypto->c) < (int)ivec->length)
2665178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2666178825Sdfr
2667178825Sdfr    if (crypto->key.data == NULL)
2668178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2669178825Sdfr
2670178825Sdfr    if (ivec)
2671178825Sdfr	idata = ivec->data;
2672178825Sdfr
2673178825Sdfr    EVP_CIPHER_CTX_init(&evp);
2674178825Sdfr
2675178825Sdfr    ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
2676178825Sdfr			    crypto->key.data, idata, 0);
2677178825Sdfr    if (ret != 1) {
2678178825Sdfr	EVP_CIPHER_CTX_cleanup(&evp);
2679178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2680178825Sdfr    }
2681178825Sdfr
2682178825Sdfr    clear->length = length;
2683178825Sdfr    clear->data = malloc(length);
2684178825Sdfr    if (clear->data == NULL) {
2685178825Sdfr	EVP_CIPHER_CTX_cleanup(&evp);
2686178825Sdfr	clear->length = 0;
2687178825Sdfr	return ENOMEM;
2688178825Sdfr    }
2689178825Sdfr
2690178825Sdfr    if (EVP_Cipher(&evp, clear->data, data, length) != 1) {
2691178825Sdfr	return HX509_CRYPTO_INTERNAL_ERROR;
2692178825Sdfr    }
2693178825Sdfr    EVP_CIPHER_CTX_cleanup(&evp);
2694178825Sdfr
2695233294Sstas    if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) {
2696178825Sdfr	int padsize;
2697233294Sstas	unsigned char *p;
2698178825Sdfr	int j, bsize = EVP_CIPHER_block_size(crypto->c);
2699178825Sdfr
2700233294Sstas	if ((int)clear->length < bsize) {
2701178825Sdfr	    ret = HX509_CMS_PADDING_ERROR;
2702178825Sdfr	    goto out;
2703178825Sdfr	}
2704178825Sdfr
2705178825Sdfr	p = clear->data;
2706178825Sdfr	p += clear->length - 1;
2707178825Sdfr	padsize = *p;
2708178825Sdfr	if (padsize > bsize) {
2709178825Sdfr	    ret = HX509_CMS_PADDING_ERROR;
2710178825Sdfr	    goto out;
2711178825Sdfr	}
2712178825Sdfr	clear->length -= padsize;
2713178825Sdfr	for (j = 0; j < padsize; j++) {
2714178825Sdfr	    if (*p-- != padsize) {
2715178825Sdfr		ret = HX509_CMS_PADDING_ERROR;
2716178825Sdfr		goto out;
2717178825Sdfr	    }
2718178825Sdfr	}
2719178825Sdfr    }
2720178825Sdfr
2721178825Sdfr    return 0;
2722178825Sdfr
2723178825Sdfr out:
2724178825Sdfr    if (clear->data)
2725178825Sdfr	free(clear->data);
2726178825Sdfr    clear->data = NULL;
2727178825Sdfr    clear->length = 0;
2728178825Sdfr    return ret;
2729178825Sdfr}
2730178825Sdfr
2731178825Sdfrtypedef int (*PBE_string2key_func)(hx509_context,
2732178825Sdfr				   const char *,
2733178825Sdfr				   const heim_octet_string *,
2734233294Sstas				   hx509_crypto *, heim_octet_string *,
2735178825Sdfr				   heim_octet_string *,
2736178825Sdfr				   const heim_oid *, const EVP_MD *);
2737178825Sdfr
2738178825Sdfrstatic int
2739178825SdfrPBE_string2key(hx509_context context,
2740178825Sdfr	       const char *password,
2741178825Sdfr	       const heim_octet_string *parameters,
2742233294Sstas	       hx509_crypto *crypto,
2743178825Sdfr	       heim_octet_string *key, heim_octet_string *iv,
2744178825Sdfr	       const heim_oid *enc_oid,
2745178825Sdfr	       const EVP_MD *md)
2746178825Sdfr{
2747178825Sdfr    PKCS12_PBEParams p12params;
2748178825Sdfr    int passwordlen;
2749178825Sdfr    hx509_crypto c;
2750178825Sdfr    int iter, saltlen, ret;
2751178825Sdfr    unsigned char *salt;
2752178825Sdfr
2753178825Sdfr    passwordlen = password ? strlen(password) : 0;
2754178825Sdfr
2755178825Sdfr    if (parameters == NULL)
2756178825Sdfr 	return HX509_ALG_NOT_SUPP;
2757178825Sdfr
2758178825Sdfr    ret = decode_PKCS12_PBEParams(parameters->data,
2759178825Sdfr				  parameters->length,
2760178825Sdfr				  &p12params, NULL);
2761178825Sdfr    if (ret)
2762178825Sdfr	goto out;
2763178825Sdfr
2764178825Sdfr    if (p12params.iterations)
2765178825Sdfr	iter = *p12params.iterations;
2766178825Sdfr    else
2767178825Sdfr	iter = 1;
2768178825Sdfr    salt = p12params.salt.data;
2769178825Sdfr    saltlen = p12params.salt.length;
2770178825Sdfr
2771233294Sstas    if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
2772178825Sdfr			 PKCS12_KEY_ID, iter, key->length, key->data, md)) {
2773178825Sdfr	ret = HX509_CRYPTO_INTERNAL_ERROR;
2774178825Sdfr	goto out;
2775178825Sdfr    }
2776233294Sstas
2777233294Sstas    if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
2778178825Sdfr			 PKCS12_IV_ID, iter, iv->length, iv->data, md)) {
2779178825Sdfr	ret = HX509_CRYPTO_INTERNAL_ERROR;
2780178825Sdfr	goto out;
2781178825Sdfr    }
2782178825Sdfr
2783178825Sdfr    ret = hx509_crypto_init(context, NULL, enc_oid, &c);
2784178825Sdfr    if (ret)
2785178825Sdfr	goto out;
2786178825Sdfr
2787233294Sstas    hx509_crypto_allow_weak(c);
2788233294Sstas
2789178825Sdfr    ret = hx509_crypto_set_key_data(c, key->data, key->length);
2790178825Sdfr    if (ret) {
2791178825Sdfr	hx509_crypto_destroy(c);
2792178825Sdfr	goto out;
2793178825Sdfr    }
2794178825Sdfr
2795178825Sdfr    *crypto = c;
2796178825Sdfrout:
2797178825Sdfr    free_PKCS12_PBEParams(&p12params);
2798178825Sdfr    return ret;
2799178825Sdfr}
2800178825Sdfr
2801178825Sdfrstatic const heim_oid *
2802233294Sstasfind_string2key(const heim_oid *oid,
2803233294Sstas		const EVP_CIPHER **c,
2804178825Sdfr		const EVP_MD **md,
2805178825Sdfr		PBE_string2key_func *s2k)
2806178825Sdfr{
2807233294Sstas    if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) {
2808178825Sdfr	*c = EVP_rc2_40_cbc();
2809178825Sdfr	*md = EVP_sha1();
2810178825Sdfr	*s2k = PBE_string2key;
2811233294Sstas	return &asn1_oid_private_rc2_40;
2812233294Sstas    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) {
2813178825Sdfr	*c = EVP_rc2_cbc();
2814178825Sdfr	*md = EVP_sha1();
2815178825Sdfr	*s2k = PBE_string2key;
2816233294Sstas	return ASN1_OID_ID_PKCS3_RC2_CBC;
2817178825Sdfr#if 0
2818233294Sstas    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) {
2819178825Sdfr	*c = EVP_rc4_40();
2820178825Sdfr	*md = EVP_sha1();
2821178825Sdfr	*s2k = PBE_string2key;
2822178825Sdfr	return NULL;
2823233294Sstas    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) {
2824178825Sdfr	*c = EVP_rc4();
2825178825Sdfr	*md = EVP_sha1();
2826178825Sdfr	*s2k = PBE_string2key;
2827233294Sstas	return ASN1_OID_ID_PKCS3_RC4;
2828178825Sdfr#endif
2829233294Sstas    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) {
2830178825Sdfr	*c = EVP_des_ede3_cbc();
2831178825Sdfr	*md = EVP_sha1();
2832178825Sdfr	*s2k = PBE_string2key;
2833233294Sstas	return ASN1_OID_ID_PKCS3_DES_EDE3_CBC;
2834178825Sdfr    }
2835178825Sdfr
2836178825Sdfr    return NULL;
2837178825Sdfr}
2838178825Sdfr
2839178825Sdfr/*
2840178825Sdfr *
2841178825Sdfr */
2842178825Sdfr
2843178825Sdfrint
2844178825Sdfr_hx509_pbe_encrypt(hx509_context context,
2845178825Sdfr		   hx509_lock lock,
2846178825Sdfr		   const AlgorithmIdentifier *ai,
2847178825Sdfr		   const heim_octet_string *content,
2848178825Sdfr		   heim_octet_string *econtent)
2849178825Sdfr{
2850178825Sdfr    hx509_clear_error_string(context);
2851178825Sdfr    return EINVAL;
2852178825Sdfr}
2853178825Sdfr
2854178825Sdfr/*
2855178825Sdfr *
2856178825Sdfr */
2857178825Sdfr
2858178825Sdfrint
2859178825Sdfr_hx509_pbe_decrypt(hx509_context context,
2860178825Sdfr		   hx509_lock lock,
2861178825Sdfr		   const AlgorithmIdentifier *ai,
2862178825Sdfr		   const heim_octet_string *econtent,
2863178825Sdfr		   heim_octet_string *content)
2864178825Sdfr{
2865178825Sdfr    const struct _hx509_password *pw;
2866178825Sdfr    heim_octet_string key, iv;
2867178825Sdfr    const heim_oid *enc_oid;
2868178825Sdfr    const EVP_CIPHER *c;
2869178825Sdfr    const EVP_MD *md;
2870178825Sdfr    PBE_string2key_func s2k;
2871233294Sstas    int ret = 0;
2872233294Sstas    size_t i;
2873178825Sdfr
2874178825Sdfr    memset(&key, 0, sizeof(key));
2875178825Sdfr    memset(&iv, 0, sizeof(iv));
2876178825Sdfr
2877178825Sdfr    memset(content, 0, sizeof(*content));
2878178825Sdfr
2879178825Sdfr    enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k);
2880178825Sdfr    if (enc_oid == NULL) {
2881178825Sdfr	hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
2882178825Sdfr			       "String to key algorithm not supported");
2883178825Sdfr	ret = HX509_ALG_NOT_SUPP;
2884178825Sdfr	goto out;
2885178825Sdfr    }
2886178825Sdfr
2887178825Sdfr    key.length = EVP_CIPHER_key_length(c);
2888178825Sdfr    key.data = malloc(key.length);
2889178825Sdfr    if (key.data == NULL) {
2890178825Sdfr	ret = ENOMEM;
2891178825Sdfr	hx509_clear_error_string(context);
2892178825Sdfr	goto out;
2893178825Sdfr    }
2894178825Sdfr
2895178825Sdfr    iv.length = EVP_CIPHER_iv_length(c);
2896178825Sdfr    iv.data = malloc(iv.length);
2897178825Sdfr    if (iv.data == NULL) {
2898178825Sdfr	ret = ENOMEM;
2899178825Sdfr	hx509_clear_error_string(context);
2900178825Sdfr	goto out;
2901178825Sdfr    }
2902178825Sdfr
2903178825Sdfr    pw = _hx509_lock_get_passwords(lock);
2904178825Sdfr
2905178825Sdfr    ret = HX509_CRYPTO_INTERNAL_ERROR;
2906178825Sdfr    for (i = 0; i < pw->len + 1; i++) {
2907178825Sdfr	hx509_crypto crypto;
2908178825Sdfr	const char *password;
2909178825Sdfr
2910178825Sdfr	if (i < pw->len)
2911178825Sdfr	    password = pw->val[i];
2912178825Sdfr	else if (i < pw->len + 1)
2913178825Sdfr	    password = "";
2914178825Sdfr	else
2915178825Sdfr	    password = NULL;
2916178825Sdfr
2917233294Sstas	ret = (*s2k)(context, password, ai->parameters, &crypto,
2918178825Sdfr		     &key, &iv, enc_oid, md);
2919178825Sdfr	if (ret)
2920178825Sdfr	    goto out;
2921178825Sdfr
2922178825Sdfr	ret = hx509_crypto_decrypt(crypto,
2923178825Sdfr				   econtent->data,
2924178825Sdfr				   econtent->length,
2925178825Sdfr				   &iv,
2926178825Sdfr				   content);
2927178825Sdfr	hx509_crypto_destroy(crypto);
2928178825Sdfr	if (ret == 0)
2929178825Sdfr	    goto out;
2930233294Sstas
2931178825Sdfr    }
2932178825Sdfrout:
2933178825Sdfr    if (key.data)
2934178825Sdfr	der_free_octet_string(&key);
2935178825Sdfr    if (iv.data)
2936178825Sdfr	der_free_octet_string(&iv);
2937178825Sdfr    return ret;
2938178825Sdfr}
2939178825Sdfr
2940178825Sdfr/*
2941178825Sdfr *
2942178825Sdfr */
2943178825Sdfr
2944178825Sdfr
2945233294Sstasstatic int
2946233294Sstasmatch_keys_rsa(hx509_cert c, hx509_private_key private_key)
2947178825Sdfr{
2948178825Sdfr    const Certificate *cert;
2949178825Sdfr    const SubjectPublicKeyInfo *spi;
2950178825Sdfr    RSAPublicKey pk;
2951178825Sdfr    RSA *rsa;
2952178825Sdfr    size_t size;
2953178825Sdfr    int ret;
2954178825Sdfr
2955178825Sdfr    if (private_key->private_key.rsa == NULL)
2956178825Sdfr	return 0;
2957178825Sdfr
2958178825Sdfr    rsa = private_key->private_key.rsa;
2959178825Sdfr    if (rsa->d == NULL || rsa->p == NULL || rsa->q == NULL)
2960178825Sdfr	return 0;
2961178825Sdfr
2962178825Sdfr    cert = _hx509_get_cert(c);
2963178825Sdfr    spi = &cert->tbsCertificate.subjectPublicKeyInfo;
2964178825Sdfr
2965178825Sdfr    rsa = RSA_new();
2966178825Sdfr    if (rsa == NULL)
2967178825Sdfr	return 0;
2968178825Sdfr
2969178825Sdfr    ret = decode_RSAPublicKey(spi->subjectPublicKey.data,
2970178825Sdfr			      spi->subjectPublicKey.length / 8,
2971178825Sdfr			      &pk, &size);
2972178825Sdfr    if (ret) {
2973178825Sdfr	RSA_free(rsa);
2974178825Sdfr	return 0;
2975178825Sdfr    }
2976178825Sdfr    rsa->n = heim_int2BN(&pk.modulus);
2977178825Sdfr    rsa->e = heim_int2BN(&pk.publicExponent);
2978178825Sdfr
2979178825Sdfr    free_RSAPublicKey(&pk);
2980178825Sdfr
2981178825Sdfr    rsa->d = BN_dup(private_key->private_key.rsa->d);
2982178825Sdfr    rsa->p = BN_dup(private_key->private_key.rsa->p);
2983178825Sdfr    rsa->q = BN_dup(private_key->private_key.rsa->q);
2984178825Sdfr    rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
2985178825Sdfr    rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1);
2986178825Sdfr    rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp);
2987178825Sdfr
2988233294Sstas    if (rsa->n == NULL || rsa->e == NULL ||
2989178825Sdfr	rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||
2990178825Sdfr	rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
2991178825Sdfr	RSA_free(rsa);
2992178825Sdfr	return 0;
2993178825Sdfr    }
2994178825Sdfr
2995178825Sdfr    ret = RSA_check_key(rsa);
2996178825Sdfr    RSA_free(rsa);
2997178825Sdfr
2998178825Sdfr    return ret == 1;
2999178825Sdfr}
3000178825Sdfr
3001233294Sstasstatic int
3002233294Sstasmatch_keys_ec(hx509_cert c, hx509_private_key private_key)
3003233294Sstas{
3004233294Sstas    return 1; /* XXX use EC_KEY_check_key */
3005233294Sstas}
3006233294Sstas
3007233294Sstas
3008233294Sstasint
3009233294Sstas_hx509_match_keys(hx509_cert c, hx509_private_key key)
3010233294Sstas{
3011233294Sstas    if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0)
3012233294Sstas	return match_keys_rsa(c, key);
3013233294Sstas    if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0)
3014233294Sstas	return match_keys_ec(c, key);
3015233294Sstas    return 0;
3016233294Sstas
3017233294Sstas}
3018233294Sstas
3019233294Sstas
3020178825Sdfrstatic const heim_oid *
3021178825Sdfrfind_keytype(const hx509_private_key key)
3022178825Sdfr{
3023178825Sdfr    const struct signature_alg *md;
3024178825Sdfr
3025178825Sdfr    if (key == NULL)
3026178825Sdfr	return NULL;
3027178825Sdfr
3028178825Sdfr    md = find_sig_alg(key->signature_alg);
3029178825Sdfr    if (md == NULL)
3030178825Sdfr	return NULL;
3031233294Sstas    return md->key_oid;
3032178825Sdfr}
3033178825Sdfr
3034178825Sdfrint
3035178825Sdfrhx509_crypto_select(const hx509_context context,
3036178825Sdfr		    int type,
3037178825Sdfr		    const hx509_private_key source,
3038178825Sdfr		    hx509_peer_info peer,
3039178825Sdfr		    AlgorithmIdentifier *selected)
3040178825Sdfr{
3041233294Sstas    const AlgorithmIdentifier *def = NULL;
3042178825Sdfr    size_t i, j;
3043178825Sdfr    int ret, bits;
3044178825Sdfr
3045178825Sdfr    memset(selected, 0, sizeof(*selected));
3046178825Sdfr
3047178825Sdfr    if (type == HX509_SELECT_DIGEST) {
3048178825Sdfr	bits = SIG_DIGEST;
3049233294Sstas	if (source)
3050233294Sstas	    def = alg_for_privatekey(source, type);
3051233294Sstas	if (def == NULL)
3052233294Sstas	    def = _hx509_crypto_default_digest_alg;
3053178825Sdfr    } else if (type == HX509_SELECT_PUBLIC_SIG) {
3054178825Sdfr	bits = SIG_PUBLIC_SIG;
3055233294Sstas	/* XXX depend on `source�� and `peer�� */
3056233294Sstas	if (source)
3057233294Sstas	    def = alg_for_privatekey(source, type);
3058233294Sstas	if (def == NULL)
3059233294Sstas	    def = _hx509_crypto_default_sig_alg;
3060178825Sdfr    } else if (type == HX509_SELECT_SECRET_ENC) {
3061178825Sdfr	bits = SIG_SECRET;
3062178825Sdfr	def = _hx509_crypto_default_secret_alg;
3063178825Sdfr    } else {
3064233294Sstas	hx509_set_error_string(context, 0, EINVAL,
3065178825Sdfr			       "Unknown type %d of selection", type);
3066178825Sdfr	return EINVAL;
3067178825Sdfr    }
3068178825Sdfr
3069178825Sdfr    if (peer) {
3070178825Sdfr	const heim_oid *keytype = NULL;
3071178825Sdfr
3072178825Sdfr	keytype = find_keytype(source);
3073178825Sdfr
3074178825Sdfr	for (i = 0; i < peer->len; i++) {
3075178825Sdfr	    for (j = 0; sig_algs[j]; j++) {
3076178825Sdfr		if ((sig_algs[j]->flags & bits) != bits)
3077178825Sdfr		    continue;
3078233294Sstas		if (der_heim_oid_cmp(sig_algs[j]->sig_oid,
3079178825Sdfr				     &peer->val[i].algorithm) != 0)
3080178825Sdfr		    continue;
3081233294Sstas		if (keytype && sig_algs[j]->key_oid &&
3082233294Sstas		    der_heim_oid_cmp(keytype, sig_algs[j]->key_oid))
3083178825Sdfr		    continue;
3084178825Sdfr
3085178825Sdfr		/* found one, use that */
3086178825Sdfr		ret = copy_AlgorithmIdentifier(&peer->val[i], selected);
3087178825Sdfr		if (ret)
3088178825Sdfr		    hx509_clear_error_string(context);
3089178825Sdfr		return ret;
3090178825Sdfr	    }
3091178825Sdfr	    if (bits & SIG_SECRET) {
3092178825Sdfr		const struct hx509cipher *cipher;
3093178825Sdfr
3094178825Sdfr		cipher = find_cipher_by_oid(&peer->val[i].algorithm);
3095178825Sdfr		if (cipher == NULL)
3096178825Sdfr		    continue;
3097178825Sdfr		if (cipher->ai_func == NULL)
3098178825Sdfr		    continue;
3099178825Sdfr		ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected);
3100178825Sdfr		if (ret)
3101178825Sdfr		    hx509_clear_error_string(context);
3102178825Sdfr		return ret;
3103178825Sdfr	    }
3104178825Sdfr	}
3105178825Sdfr    }
3106178825Sdfr
3107178825Sdfr    /* use default */
3108178825Sdfr    ret = copy_AlgorithmIdentifier(def, selected);
3109178825Sdfr    if (ret)
3110178825Sdfr	hx509_clear_error_string(context);
3111178825Sdfr    return ret;
3112178825Sdfr}
3113178825Sdfr
3114178825Sdfrint
3115178825Sdfrhx509_crypto_available(hx509_context context,
3116178825Sdfr		       int type,
3117178825Sdfr		       hx509_cert source,
3118178825Sdfr		       AlgorithmIdentifier **val,
3119178825Sdfr		       unsigned int *plen)
3120178825Sdfr{
3121178825Sdfr    const heim_oid *keytype = NULL;
3122178825Sdfr    unsigned int len, i;
3123178825Sdfr    void *ptr;
3124178825Sdfr    int bits, ret;
3125178825Sdfr
3126178825Sdfr    *val = NULL;
3127178825Sdfr
3128178825Sdfr    if (type == HX509_SELECT_ALL) {
3129178825Sdfr	bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET;
3130178825Sdfr    } else if (type == HX509_SELECT_DIGEST) {
3131178825Sdfr	bits = SIG_DIGEST;
3132178825Sdfr    } else if (type == HX509_SELECT_PUBLIC_SIG) {
3133178825Sdfr	bits = SIG_PUBLIC_SIG;
3134178825Sdfr    } else {
3135233294Sstas	hx509_set_error_string(context, 0, EINVAL,
3136178825Sdfr			       "Unknown type %d of available", type);
3137178825Sdfr	return EINVAL;
3138178825Sdfr    }
3139178825Sdfr
3140178825Sdfr    if (source)
3141178825Sdfr	keytype = find_keytype(_hx509_cert_private_key(source));
3142178825Sdfr
3143178825Sdfr    len = 0;
3144178825Sdfr    for (i = 0; sig_algs[i]; i++) {
3145178825Sdfr	if ((sig_algs[i]->flags & bits) == 0)
3146178825Sdfr	    continue;
3147178825Sdfr	if (sig_algs[i]->sig_alg == NULL)
3148178825Sdfr	    continue;
3149233294Sstas	if (keytype && sig_algs[i]->key_oid &&
3150233294Sstas	    der_heim_oid_cmp(sig_algs[i]->key_oid, keytype))
3151178825Sdfr	    continue;
3152178825Sdfr
3153178825Sdfr	/* found one, add that to the list */
3154178825Sdfr	ptr = realloc(*val, sizeof(**val) * (len + 1));
3155178825Sdfr	if (ptr == NULL)
3156178825Sdfr	    goto out;
3157178825Sdfr	*val = ptr;
3158178825Sdfr
3159233294Sstas	ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]);
3160178825Sdfr	if (ret)
3161178825Sdfr	    goto out;
3162178825Sdfr	len++;
3163178825Sdfr    }
3164178825Sdfr
3165178825Sdfr    /* Add AES */
3166178825Sdfr    if (bits & SIG_SECRET) {
3167178825Sdfr
3168178825Sdfr	for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
3169233294Sstas
3170233294Sstas	    if (ciphers[i].flags & CIPHER_WEAK)
3171233294Sstas		continue;
3172178825Sdfr	    if (ciphers[i].ai_func == NULL)
3173178825Sdfr		continue;
3174178825Sdfr
3175178825Sdfr	    ptr = realloc(*val, sizeof(**val) * (len + 1));
3176178825Sdfr	    if (ptr == NULL)
3177178825Sdfr		goto out;
3178178825Sdfr	    *val = ptr;
3179233294Sstas
3180178825Sdfr	    ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]);
3181178825Sdfr	    if (ret)
3182178825Sdfr		goto out;
3183178825Sdfr	    len++;
3184178825Sdfr	}
3185178825Sdfr    }
3186178825Sdfr
3187178825Sdfr    *plen = len;
3188178825Sdfr    return 0;
3189178825Sdfr
3190178825Sdfrout:
3191178825Sdfr    for (i = 0; i < len; i++)
3192178825Sdfr	free_AlgorithmIdentifier(&(*val)[i]);
3193178825Sdfr    free(*val);
3194178825Sdfr    *val = NULL;
3195178825Sdfr    hx509_set_error_string(context, 0, ENOMEM, "out of memory");
3196178825Sdfr    return ENOMEM;
3197178825Sdfr}
3198178825Sdfr
3199178825Sdfrvoid
3200178825Sdfrhx509_crypto_free_algs(AlgorithmIdentifier *val,
3201178825Sdfr		       unsigned int len)
3202178825Sdfr{
3203178825Sdfr    unsigned int i;
3204178825Sdfr    for (i = 0; i < len; i++)
3205178825Sdfr	free_AlgorithmIdentifier(&val[i]);
3206178825Sdfr    free(val);
3207233294Sstas}
3208