Rename all getters to use get/get0 in name
[openssl.git] / crypto / cms / cms_ec.c
1 /*
2  * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <assert.h>
11 #include <openssl/cms.h>
12 #include <openssl/err.h>
13 #include <openssl/decoder.h>
14 #include "internal/sizes.h"
15 #include "crypto/evp.h"
16 #include "cms_local.h"
17
18 static EVP_PKEY *pkey_type2param(int ptype, const void *pval,
19                                  OSSL_LIB_CTX *libctx, const char *propq)
20 {
21     EVP_PKEY *pkey = NULL;
22     EVP_PKEY_CTX *pctx = NULL;
23
24     if (ptype == V_ASN1_SEQUENCE) {
25         const ASN1_STRING *pstr = pval;
26         const unsigned char *pm = pstr->data;
27         size_t pmlen = (size_t)pstr->length;
28         OSSL_DECODER_CTX *ctx = NULL;
29         int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
30
31         ctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC",
32                                             selection, libctx, propq);
33         if (ctx == NULL)
34             goto err;
35
36         OSSL_DECODER_from_data(ctx, &pm, &pmlen);
37         OSSL_DECODER_CTX_free(ctx);
38     } else if (ptype == V_ASN1_OBJECT) {
39         const ASN1_OBJECT *poid = pval;
40         char groupname[OSSL_MAX_NAME_SIZE];
41
42         /* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID */
43         pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
44         if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0)
45             goto err;
46         if (!OBJ_obj2txt(groupname, sizeof(groupname), poid, 0)
47                 || !EVP_PKEY_CTX_set_group_name(pctx, groupname)) {
48             ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
49             goto err;
50         }
51         if (EVP_PKEY_paramgen(pctx, &pkey) <= 0)
52             goto err;
53     } else {
54         ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
55         goto err;
56     }
57
58     return pkey;
59
60  err:
61     EVP_PKEY_free(pkey);
62     EVP_PKEY_CTX_free(pctx);
63     return NULL;
64 }
65
66 static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
67                                 X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
68 {
69     const ASN1_OBJECT *aoid;
70     int atype;
71     const void *aval;
72     int rv = 0;
73     EVP_PKEY *pkpeer = NULL;
74     const unsigned char *p;
75     int plen;
76
77     X509_ALGOR_get0(&aoid, &atype, &aval, alg);
78     if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
79         goto err;
80
81     /* If absent parameters get group from main key */
82     if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
83         EVP_PKEY *pk;
84
85         pk = EVP_PKEY_CTX_get0_pkey(pctx);
86         if (pk == NULL)
87             goto err;
88
89         pkpeer = EVP_PKEY_new();
90         if (pkpeer == NULL)
91             goto err;
92         if (!EVP_PKEY_copy_parameters(pkpeer, pk))
93             goto err;
94     } else {
95         pkpeer = pkey_type2param(atype, aval,
96                                  EVP_PKEY_CTX_get0_libctx(pctx),
97                                  EVP_PKEY_CTX_get0_propq(pctx));
98         if (pkpeer == NULL)
99             goto err;
100     }
101     /* We have parameters now set public key */
102     plen = ASN1_STRING_length(pubkey);
103     p = ASN1_STRING_get0_data(pubkey);
104     if (p == NULL || plen == 0)
105         goto err;
106
107     if (!EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen))
108         goto err;
109
110     if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
111         rv = 1;
112  err:
113     EVP_PKEY_free(pkpeer);
114     return rv;
115 }
116
117 /* Set KDF parameters based on KDF NID */
118 static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
119 {
120     int kdf_nid, kdfmd_nid, cofactor;
121     const EVP_MD *kdf_md;
122
123     if (eckdf_nid == NID_undef)
124         return 0;
125
126     /* Lookup KDF type, cofactor mode and digest */
127     if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
128         return 0;
129
130     if (kdf_nid == NID_dh_std_kdf)
131         cofactor = 0;
132     else if (kdf_nid == NID_dh_cofactor_kdf)
133         cofactor = 1;
134     else
135         return 0;
136
137     if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
138         return 0;
139
140     if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
141         return 0;
142
143     kdf_md = EVP_get_digestbynid(kdfmd_nid);
144     if (!kdf_md)
145         return 0;
146
147     if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
148         return 0;
149     return 1;
150 }
151
152 static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
153 {
154     int rv = 0;
155     X509_ALGOR *alg, *kekalg = NULL;
156     ASN1_OCTET_STRING *ukm;
157     const unsigned char *p;
158     unsigned char *der = NULL;
159     int plen, keylen;
160     EVP_CIPHER *kekcipher = NULL;
161     EVP_CIPHER_CTX *kekctx;
162     char name[OSSL_MAX_NAME_SIZE];
163
164     if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
165         return 0;
166
167     if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
168         ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
169         return 0;
170     }
171
172     if (alg->parameter->type != V_ASN1_SEQUENCE)
173         return 0;
174
175     p = alg->parameter->value.sequence->data;
176     plen = alg->parameter->value.sequence->length;
177     kekalg = d2i_X509_ALGOR(NULL, &p, plen);
178     if (kekalg == NULL)
179         goto err;
180     kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
181     if (kekctx == NULL)
182         goto err;
183     OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0);
184     kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
185     if (kekcipher == NULL || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
186         goto err;
187     if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
188         goto err;
189     if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
190         goto err;
191
192     keylen = EVP_CIPHER_CTX_get_key_length(kekctx);
193     if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
194         goto err;
195
196     plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
197
198     if (plen <= 0)
199         goto err;
200
201     if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
202         goto err;
203     der = NULL;
204
205     rv = 1;
206  err:
207     EVP_CIPHER_free(kekcipher);
208     X509_ALGOR_free(kekalg);
209     OPENSSL_free(der);
210     return rv;
211 }
212
213 static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
214 {
215     EVP_PKEY_CTX *pctx;
216
217     pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
218     if (pctx == NULL)
219         return 0;
220     /* See if we need to set peer key */
221     if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
222         X509_ALGOR *alg;
223         ASN1_BIT_STRING *pubkey;
224
225         if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
226                                                  NULL, NULL, NULL))
227             return 0;
228         if (alg == NULL || pubkey == NULL)
229             return 0;
230         if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
231             ERR_raise(ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR);
232             return 0;
233         }
234     }
235     /* Set ECDH derivation parameters and initialise unwrap context */
236     if (!ecdh_cms_set_shared_info(pctx, ri)) {
237         ERR_raise(ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR);
238         return 0;
239     }
240     return 1;
241 }
242
243 static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
244 {
245     EVP_PKEY_CTX *pctx;
246     EVP_PKEY *pkey;
247     EVP_CIPHER_CTX *ctx;
248     int keylen;
249     X509_ALGOR *talg, *wrap_alg = NULL;
250     const ASN1_OBJECT *aoid;
251     ASN1_BIT_STRING *pubkey;
252     ASN1_STRING *wrap_str;
253     ASN1_OCTET_STRING *ukm;
254     unsigned char *penc = NULL;
255     size_t penclen;
256     int rv = 0;
257     int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
258     const EVP_MD *kdf_md;
259
260     pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
261     if (pctx == NULL)
262         return 0;
263     /* Get ephemeral key */
264     pkey = EVP_PKEY_CTX_get0_pkey(pctx);
265     if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
266                                              NULL, NULL, NULL))
267         goto err;
268     X509_ALGOR_get0(&aoid, NULL, NULL, talg);
269     /* Is everything uninitialised? */
270     if (aoid == OBJ_nid2obj(NID_undef)) {
271         /* Set the key */
272
273         penclen = EVP_PKEY_get1_encoded_public_key(pkey, &penc);
274         ASN1_STRING_set0(pubkey, penc, penclen);
275         pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
276         pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
277
278         penc = NULL;
279         X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
280                         V_ASN1_UNDEF, NULL);
281     }
282
283     /* See if custom parameters set */
284     kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
285     if (kdf_type <= 0)
286         goto err;
287     if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
288         goto err;
289     ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
290     if (ecdh_nid < 0)
291         goto err;
292     else if (ecdh_nid == 0)
293         ecdh_nid = NID_dh_std_kdf;
294     else if (ecdh_nid == 1)
295         ecdh_nid = NID_dh_cofactor_kdf;
296
297     if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
298         kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
299         if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
300             goto err;
301     } else
302         /* Unknown KDF */
303         goto err;
304     if (kdf_md == NULL) {
305         /* Fixme later for better MD */
306         kdf_md = EVP_sha1();
307         if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
308             goto err;
309     }
310
311     if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
312         goto err;
313
314     /* Lookup NID for KDF+cofactor+digest */
315
316     if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_get_type(kdf_md), ecdh_nid))
317         goto err;
318     /* Get wrap NID */
319     ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
320     wrap_nid = EVP_CIPHER_CTX_get_type(ctx);
321     keylen = EVP_CIPHER_CTX_get_key_length(ctx);
322
323     /* Package wrap algorithm in an AlgorithmIdentifier */
324
325     wrap_alg = X509_ALGOR_new();
326     if (wrap_alg == NULL)
327         goto err;
328     wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
329     wrap_alg->parameter = ASN1_TYPE_new();
330     if (wrap_alg->parameter == NULL)
331         goto err;
332     if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
333         goto err;
334     if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
335         ASN1_TYPE_free(wrap_alg->parameter);
336         wrap_alg->parameter = NULL;
337     }
338
339     if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
340         goto err;
341
342     penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
343
344     if (penclen == 0)
345         goto err;
346
347     if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
348         goto err;
349     penc = NULL;
350
351     /*
352      * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
353      * of another AlgorithmIdentifier.
354      */
355     penclen = i2d_X509_ALGOR(wrap_alg, &penc);
356     if (penc == NULL || penclen == 0)
357         goto err;
358     wrap_str = ASN1_STRING_new();
359     if (wrap_str == NULL)
360         goto err;
361     ASN1_STRING_set0(wrap_str, penc, penclen);
362     penc = NULL;
363     X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
364
365     rv = 1;
366
367  err:
368     OPENSSL_free(penc);
369     X509_ALGOR_free(wrap_alg);
370     return rv;
371 }
372
373 int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt)
374 {
375     assert(decrypt == 0 || decrypt == 1);
376
377     if (decrypt == 1)
378         return ecdh_cms_decrypt(ri);
379
380     if (decrypt == 0)
381         return ecdh_cms_encrypt(ri);
382
383     ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
384     return 0;
385 }
386
387 /* ECDSA and DSA implementation is the same */
388 int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify)
389 {
390     assert(verify == 0 || verify == 1);
391
392     if (verify == 0) {
393         int snid, hnid;
394         X509_ALGOR *alg1, *alg2;
395         EVP_PKEY *pkey = si->pkey;
396
397         CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2);
398         if (alg1 == NULL || alg1->algorithm == NULL)
399             return -1;
400         hnid = OBJ_obj2nid(alg1->algorithm);
401         if (hnid == NID_undef)
402             return -1;
403         if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey)))
404             return -1;
405         X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
406     }
407     return 1;
408 }