s4:heimdal: import lorikeet-heimdal-202201172009 (commit 5a0b45cd723628b3690ea848548b...
[samba.git] / source4 / heimdal / lib / hx509 / crypto-ec.c
1 /*
2  * Copyright (c) 2016 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include <config.h>
35
36 #ifdef HAVE_HCRYPTO_W_OPENSSL
37 #include <openssl/ec.h>
38 #include <openssl/ecdsa.h>
39 #include <openssl/rsa.h>
40 #include <openssl/bn.h>
41 #include <openssl/objects.h>
42 #define HEIM_NO_CRYPTO_HDRS
43 #endif /* HAVE_HCRYPTO_W_OPENSSL */
44
45 #include "hx_locl.h"
46
47 extern const AlgorithmIdentifier _hx509_signature_sha512_data;
48 extern const AlgorithmIdentifier _hx509_signature_sha384_data;
49 extern const AlgorithmIdentifier _hx509_signature_sha256_data;
50 extern const AlgorithmIdentifier _hx509_signature_sha1_data;
51
52 HX509_LIB_FUNCTION void HX509_LIB_CALL
53 _hx509_private_eckey_free(void *eckey)
54 {
55 #ifdef HAVE_HCRYPTO_W_OPENSSL
56     EC_KEY_free(eckey);
57 #endif
58 }
59
60 #ifdef HAVE_HCRYPTO_W_OPENSSL
61 static int
62 heim_oid2ecnid(heim_oid *oid)
63 {
64     /*
65      * Now map to openssl OID fun
66      */
67
68     if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
69         return NID_X9_62_prime256v1;
70 #ifdef NID_secp521r1
71     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP521R1) == 0)
72         return NID_secp521r1;
73 #endif
74 #ifdef NID_secp384r1
75     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP384R1) == 0)
76         return NID_secp384r1;
77 #endif
78 #ifdef NID_secp160r1
79     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
80         return NID_secp160r1;
81 #endif
82 #ifdef NID_secp160r2
83     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
84         return NID_secp160r2;
85 #endif
86
87     return NID_undef;
88 }
89
90 static int
91 parse_ECParameters(hx509_context context,
92                    heim_octet_string *parameters, int *nid)
93 {
94     ECParameters ecparam;
95     size_t size;
96     int ret;
97
98     if (parameters == NULL) {
99         ret = HX509_PARSING_KEY_FAILED;
100         hx509_set_error_string(context, 0, ret,
101                                "EC parameters missing");
102         return ret;
103     }
104
105     ret = decode_ECParameters(parameters->data, parameters->length,
106                               &ecparam, &size);
107     if (ret) {
108         hx509_set_error_string(context, 0, ret,
109                                "Failed to decode EC parameters");
110         return ret;
111     }
112
113     if (ecparam.element != choice_ECParameters_namedCurve) {
114         free_ECParameters(&ecparam);
115         hx509_set_error_string(context, 0, ret,
116                                "EC parameters is not a named curve");
117         return HX509_CRYPTO_SIG_INVALID_FORMAT;
118     }
119
120     *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
121     free_ECParameters(&ecparam);
122     if (*nid == NID_undef) {
123         hx509_set_error_string(context, 0, ret,
124                                "Failed to find matcing NID for EC curve");
125         return HX509_CRYPTO_SIG_INVALID_FORMAT;
126     }
127     return 0;
128 }
129
130
131 /*
132  *
133  */
134
135 static int
136 ecdsa_verify_signature(hx509_context context,
137                        const struct signature_alg *sig_alg,
138                        const Certificate *signer,
139                        const AlgorithmIdentifier *alg,
140                        const heim_octet_string *data,
141                        const heim_octet_string *sig)
142 {
143     const AlgorithmIdentifier *digest_alg;
144     const SubjectPublicKeyInfo *spi;
145     heim_octet_string digest;
146     int ret;
147     EC_KEY *key = NULL;
148     int groupnid;
149     EC_GROUP *group;
150     const unsigned char *p;
151     long len;
152
153     digest_alg = sig_alg->digest_alg;
154
155     ret = _hx509_create_signature(context,
156                                   NULL,
157                                   digest_alg,
158                                   data,
159                                   NULL,
160                                   &digest);
161     if (ret)
162         return ret;
163
164     /* set up EC KEY */
165     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
166
167     if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
168         return HX509_CRYPTO_SIG_INVALID_FORMAT;
169
170     /*
171      * Find the group id
172      */
173
174     ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
175     if (ret) {
176         der_free_octet_string(&digest);
177         return ret;
178     }
179
180     /*
181      * Create group, key, parse key
182      */
183
184     key = EC_KEY_new();
185     group = EC_GROUP_new_by_curve_name(groupnid);
186     EC_KEY_set_group(key, group);
187     EC_GROUP_free(group);
188
189     p = spi->subjectPublicKey.data;
190     len = spi->subjectPublicKey.length / 8;
191
192     if (o2i_ECPublicKey(&key, &p, len) == NULL) {
193         EC_KEY_free(key);
194         return HX509_CRYPTO_SIG_INVALID_FORMAT;
195     }
196
197     ret = ECDSA_verify(-1, digest.data, digest.length,
198                        sig->data, sig->length, key);
199     der_free_octet_string(&digest);
200     EC_KEY_free(key);
201     if (ret != 1) {
202         ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
203         return ret;
204     }
205
206     return 0;
207 }
208
209 static int
210 ecdsa_create_signature(hx509_context context,
211                        const struct signature_alg *sig_alg,
212                        const hx509_private_key signer,
213                        const AlgorithmIdentifier *alg,
214                        const heim_octet_string *data,
215                        AlgorithmIdentifier *signatureAlgorithm,
216                        heim_octet_string *sig)
217 {
218     const AlgorithmIdentifier *digest_alg;
219     heim_octet_string indata;
220     const heim_oid *sig_oid;
221     unsigned int siglen;
222     int ret;
223
224     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
225         _hx509_abort("internal error passing private key to wrong ops");
226
227     sig_oid = sig_alg->sig_oid;
228     digest_alg = sig_alg->digest_alg;
229
230     if (signatureAlgorithm) {
231         ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
232                                     "\x05\x00", 2);
233         if (ret) {
234             hx509_clear_error_string(context);
235             return ret;
236         }
237     }
238
239     ret = _hx509_create_signature(context,
240                                   NULL,
241                                   digest_alg,
242                                   data,
243                                   NULL,
244                                   &indata);
245     if (ret)
246         goto error;
247
248     sig->length = ECDSA_size(signer->private_key.ecdsa);
249     sig->data = malloc(sig->length);
250     if (sig->data == NULL) {
251         der_free_octet_string(&indata);
252         ret = ENOMEM;
253         hx509_set_error_string(context, 0, ret, "out of memory");
254         goto error;
255     }
256
257     siglen = sig->length;
258
259     ret = ECDSA_sign(-1, indata.data, indata.length,
260                      sig->data, &siglen, signer->private_key.ecdsa);
261     der_free_octet_string(&indata);
262     if (ret != 1) {
263         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
264         hx509_set_error_string(context, 0, ret,
265                                "ECDSA sign failed: %d", ret);
266         goto error;
267     }
268     if (siglen > sig->length)
269         _hx509_abort("ECDSA signature prelen longer the output len");
270
271     sig->length = siglen;
272
273     return 0;
274  error:
275     if (signatureAlgorithm)
276         free_AlgorithmIdentifier(signatureAlgorithm);
277     return ret;
278 }
279
280 static int
281 ecdsa_available(const hx509_private_key signer,
282                 const AlgorithmIdentifier *sig_alg)
283 {
284     const struct signature_alg *sig;
285     const EC_GROUP *group;
286     BN_CTX *bnctx = NULL;
287     BIGNUM *order = NULL;
288     int ret = 0;
289
290     if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
291         _hx509_abort("internal error passing private key to wrong ops");
292
293     sig = _hx509_find_sig_alg(&sig_alg->algorithm);
294
295     if (sig == NULL || sig->digest_size == 0)
296         return 0;
297
298     group = EC_KEY_get0_group(signer->private_key.ecdsa);
299     if (group == NULL)
300         return 0;
301
302     bnctx = BN_CTX_new();
303     order = BN_new();
304     if (order == NULL)
305         goto err;
306
307     if (EC_GROUP_get_order(group, order, bnctx) != 1)
308         goto err;
309
310 #if 0
311     /* If anything, require a digest at least as wide as the EC key size */
312     if (BN_num_bytes(order) > sig->digest_size)
313 #endif
314         ret = 1;
315  err:
316     if (bnctx)
317         BN_CTX_free(bnctx);
318     if (order)
319         BN_clear_free(order);
320
321     return ret;
322 }
323
324 static int
325 ecdsa_private_key2SPKI(hx509_context context,
326                        hx509_private_key private_key,
327                        SubjectPublicKeyInfo *spki)
328 {
329     memset(spki, 0, sizeof(*spki));
330     return ENOMEM;
331 }
332
333 static int
334 ecdsa_private_key_export(hx509_context context,
335                          const hx509_private_key key,
336                          hx509_key_format_t format,
337                          heim_octet_string *data)
338 {
339     return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
340 }
341
342 static int
343 ecdsa_private_key_import(hx509_context context,
344                          const AlgorithmIdentifier *keyai,
345                          const void *data,
346                          size_t len,
347                          hx509_key_format_t format,
348                          hx509_private_key private_key)
349 {
350     const unsigned char *p = data;
351     EC_KEY **pkey = NULL;
352     EC_KEY *key;
353
354     if (keyai->parameters) {
355         EC_GROUP *group;
356         int groupnid;
357         int ret;
358
359         ret = parse_ECParameters(context, keyai->parameters, &groupnid);
360         if (ret)
361             return ret;
362
363         key = EC_KEY_new();
364         if (key == NULL)
365             return ENOMEM;
366
367         group = EC_GROUP_new_by_curve_name(groupnid);
368         if (group == NULL) {
369             EC_KEY_free(key);
370             return ENOMEM;
371         }
372         EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
373         if (EC_KEY_set_group(key, group) == 0) {
374             EC_KEY_free(key);
375             EC_GROUP_free(group);
376             return ENOMEM;
377         }
378         EC_GROUP_free(group);
379         pkey = &key;
380     }
381
382     switch (format) {
383     case HX509_KEY_FORMAT_DER:
384
385         private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
386         if (private_key->private_key.ecdsa == NULL) {
387             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
388                                    "Failed to parse EC private key");
389             return HX509_PARSING_KEY_FAILED;
390         }
391         private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
392         break;
393
394     default:
395         return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
396     }
397
398     return 0;
399 }
400
401 static int
402 ecdsa_generate_private_key(hx509_context context,
403                            struct hx509_generate_private_context *ctx,
404                            hx509_private_key private_key)
405 {
406     return ENOMEM;
407 }
408
409 static BIGNUM *
410 ecdsa_get_internal(hx509_context context,
411                    hx509_private_key key,
412                    const char *type)
413 {
414     return NULL;
415 }
416
417 static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
418 const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
419     { 6, rk_UNCONST(ecPublicKey) }, NULL
420 };
421
422 static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
423 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
424     { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
425 };
426
427 static const unsigned ecdsa_with_sha384_oid[] ={ 1, 2, 840, 10045, 4, 3, 3 };
428 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha384_data = {
429     { 7, rk_UNCONST(ecdsa_with_sha384_oid) }, NULL
430 };
431
432 static const unsigned ecdsa_with_sha512_oid[] ={ 1, 2, 840, 10045, 4, 3, 4 };
433 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha512_data = {
434     { 7, rk_UNCONST(ecdsa_with_sha512_oid) }, NULL
435 };
436
437 static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
438 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
439     { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
440 };
441
442 hx509_private_key_ops ecdsa_private_key_ops = {
443     "EC PRIVATE KEY",
444     ASN1_OID_ID_ECPUBLICKEY,
445     ecdsa_available,
446     ecdsa_private_key2SPKI,
447     ecdsa_private_key_export,
448     ecdsa_private_key_import,
449     ecdsa_generate_private_key,
450     ecdsa_get_internal
451 };
452
453 const struct signature_alg ecdsa_with_sha512_alg = {
454     "ecdsa-with-sha512",
455     ASN1_OID_ID_ECDSA_WITH_SHA512,
456     &_hx509_signature_ecdsa_with_sha512_data,
457     ASN1_OID_ID_ECPUBLICKEY,
458     &_hx509_signature_sha512_data,
459     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
460         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
461     0,
462     NULL,
463     ecdsa_verify_signature,
464     ecdsa_create_signature,
465     64
466 };
467
468 const struct signature_alg ecdsa_with_sha384_alg = {
469     "ecdsa-with-sha384",
470     ASN1_OID_ID_ECDSA_WITH_SHA384,
471     &_hx509_signature_ecdsa_with_sha384_data,
472     ASN1_OID_ID_ECPUBLICKEY,
473     &_hx509_signature_sha384_data,
474     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
475         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
476     0,
477     NULL,
478     ecdsa_verify_signature,
479     ecdsa_create_signature,
480     48
481 };
482
483 const struct signature_alg ecdsa_with_sha256_alg = {
484     "ecdsa-with-sha256",
485     ASN1_OID_ID_ECDSA_WITH_SHA256,
486     &_hx509_signature_ecdsa_with_sha256_data,
487     ASN1_OID_ID_ECPUBLICKEY,
488     &_hx509_signature_sha256_data,
489     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
490         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
491     0,
492     NULL,
493     ecdsa_verify_signature,
494     ecdsa_create_signature,
495     32
496 };
497
498 const struct signature_alg ecdsa_with_sha1_alg = {
499     "ecdsa-with-sha1",
500     ASN1_OID_ID_ECDSA_WITH_SHA1,
501     &_hx509_signature_ecdsa_with_sha1_data,
502     ASN1_OID_ID_ECPUBLICKEY,
503     &_hx509_signature_sha1_data,
504     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
505         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
506     0,
507     NULL,
508     ecdsa_verify_signature,
509     ecdsa_create_signature,
510     20
511 };
512
513 #endif /* HAVE_HCRYPTO_W_OPENSSL */
514
515 HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
516 hx509_signature_ecPublicKey(void)
517 {
518 #ifdef HAVE_HCRYPTO_W_OPENSSL
519     return &_hx509_signature_ecPublicKey;
520 #else
521     return NULL;
522 #endif /* HAVE_HCRYPTO_W_OPENSSL */
523 }
524
525 HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
526 hx509_signature_ecdsa_with_sha256(void)
527 {
528 #ifdef HAVE_HCRYPTO_W_OPENSSL
529     return &_hx509_signature_ecdsa_with_sha256_data;
530 #else
531     return NULL;
532 #endif /* HAVE_HCRYPTO_W_OPENSSL */
533 }