Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/evp/p_ec_asn1.c
Line
Count
Source (jump to first uncovered line)
1
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2
 * project 2006.
3
 */
4
/* ====================================================================
5
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer. 
13
 *
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in
16
 *    the documentation and/or other materials provided with the
17
 *    distribution.
18
 *
19
 * 3. All advertising materials mentioning features or use of this
20
 *    software must display the following acknowledgment:
21
 *    "This product includes software developed by the OpenSSL Project
22
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23
 *
24
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25
 *    endorse or promote products derived from this software without
26
 *    prior written permission. For written permission, please contact
27
 *    licensing@OpenSSL.org.
28
 *
29
 * 5. Products derived from this software may not be called "OpenSSL"
30
 *    nor may "OpenSSL" appear in their names without prior written
31
 *    permission of the OpenSSL Project.
32
 *
33
 * 6. Redistributions of any form whatsoever must retain the following
34
 *    acknowledgment:
35
 *    "This product includes software developed by the OpenSSL Project
36
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37
 *
38
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49
 * OF THE POSSIBILITY OF SUCH DAMAGE.
50
 * ====================================================================
51
 *
52
 * This product includes cryptographic software written by Eric Young
53
 * (eay@cryptsoft.com).  This product includes software written by Tim
54
 * Hudson (tjh@cryptsoft.com). */
55
56
#include <openssl/evp.h>
57
58
#include <openssl/bn.h>
59
#include <openssl/bytestring.h>
60
#include <openssl/ec.h>
61
#include <openssl/ec_key.h>
62
#include <openssl/ecdsa.h>
63
#include <openssl/err.h>
64
65
#include "internal.h"
66
67
68
0
static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
69
0
  const EC_KEY *ec_key = key->pkey;
70
0
  const EC_GROUP *group = EC_KEY_get0_group(ec_key);
71
0
  const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
72
73
  // See RFC 5480, section 2.
74
0
  CBB spki, algorithm, oid, key_bitstring;
75
0
  if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
76
0
      !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
77
0
      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
78
0
      !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
79
0
      !EC_KEY_marshal_curve_name(&algorithm, group) ||
80
0
      !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
81
0
      !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
82
0
      !EC_POINT_point2cbb(&key_bitstring, group, public_key,
83
0
                          POINT_CONVERSION_UNCOMPRESSED, NULL) ||
84
0
      !CBB_flush(out)) {
85
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
86
0
    return 0;
87
0
  }
88
89
0
  return 1;
90
0
}
91
92
0
static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
93
  // See RFC 5480, section 2.
94
95
  // The parameters are a named curve.
96
0
  EC_KEY *eckey = NULL;
97
0
  const EC_GROUP *group = EC_KEY_parse_curve_name(params);
98
0
  if (group == NULL || CBS_len(params) != 0) {
99
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
100
0
    goto err;
101
0
  }
102
103
0
  eckey = EC_KEY_new();
104
0
  if (eckey == NULL || //
105
0
      !EC_KEY_set_group(eckey, group) ||
106
0
      !EC_KEY_oct2key(eckey, CBS_data(key), CBS_len(key), NULL)) {
107
0
    goto err;
108
0
  }
109
110
0
  EVP_PKEY_assign_EC_KEY(out, eckey);
111
0
  return 1;
112
113
0
err:
114
0
  EC_KEY_free(eckey);
115
0
  return 0;
116
0
}
117
118
0
static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
119
0
  const EC_KEY *a_ec = a->pkey;
120
0
  const EC_KEY *b_ec = b->pkey;
121
0
  const EC_GROUP *group = EC_KEY_get0_group(b_ec);
122
0
  const EC_POINT *pa = EC_KEY_get0_public_key(a_ec),
123
0
                 *pb = EC_KEY_get0_public_key(b_ec);
124
0
  int r = EC_POINT_cmp(group, pa, pb, NULL);
125
0
  if (r == 0) {
126
0
    return 1;
127
0
  } else if (r == 1) {
128
0
    return 0;
129
0
  } else {
130
0
    return -2;
131
0
  }
132
0
}
133
134
0
static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
135
  // See RFC 5915.
136
0
  const EC_GROUP *group = EC_KEY_parse_parameters(params);
137
0
  if (group == NULL || CBS_len(params) != 0) {
138
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
139
0
    return 0;
140
0
  }
141
142
0
  EC_KEY *ec_key = EC_KEY_parse_private_key(key, group);
143
0
  if (ec_key == NULL || CBS_len(key) != 0) {
144
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
145
0
    EC_KEY_free(ec_key);
146
0
    return 0;
147
0
  }
148
149
0
  EVP_PKEY_assign_EC_KEY(out, ec_key);
150
0
  return 1;
151
0
}
152
153
0
static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
154
0
  const EC_KEY *ec_key = key->pkey;
155
156
  // Omit the redundant copy of the curve name. This contradicts RFC 5915 but
157
  // aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
158
  // means. Both OpenSSL and NSS omit the redundant parameters, so we omit them
159
  // as well.
160
0
  unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
161
162
  // See RFC 5915.
163
0
  CBB pkcs8, algorithm, oid, private_key;
164
0
  if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
165
0
      !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
166
0
      !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
167
0
      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
168
0
      !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
169
0
      !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
170
0
      !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
171
0
      !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
172
0
      !CBB_flush(out)) {
173
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
174
0
    return 0;
175
0
  }
176
177
0
  return 1;
178
0
}
179
180
static int eckey_set1_tls_encodedpoint(EVP_PKEY *pkey, const uint8_t *in,
181
0
                                       size_t len) {
182
0
  EC_KEY *ec_key = pkey->pkey;
183
0
  if (ec_key == NULL) {
184
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
185
0
    return 0;
186
0
  }
187
188
0
  return EC_KEY_oct2key(ec_key, in, len, NULL);
189
0
}
190
191
static size_t eckey_get1_tls_encodedpoint(const EVP_PKEY *pkey,
192
0
                                          uint8_t **out_ptr) {
193
0
  const EC_KEY *ec_key = pkey->pkey;
194
0
  if (ec_key == NULL) {
195
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
196
0
    return 0;
197
0
  }
198
199
0
  return EC_KEY_key2buf(ec_key, POINT_CONVERSION_UNCOMPRESSED, out_ptr, NULL);
200
0
}
201
202
0
static int int_ec_size(const EVP_PKEY *pkey) {
203
0
  const EC_KEY *ec_key = pkey->pkey;
204
0
  return ECDSA_size(ec_key);
205
0
}
206
207
0
static int ec_bits(const EVP_PKEY *pkey) {
208
0
  const EC_KEY *ec_key = pkey->pkey;
209
0
  const EC_GROUP *group = EC_KEY_get0_group(ec_key);
210
0
  if (group == NULL) {
211
0
    ERR_clear_error();
212
0
    return 0;
213
0
  }
214
0
  return EC_GROUP_order_bits(group);
215
0
}
216
217
0
static int ec_missing_parameters(const EVP_PKEY *pkey) {
218
0
  const EC_KEY *ec_key = pkey->pkey;
219
0
  return ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL;
220
0
}
221
222
0
static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
223
0
  const EC_KEY *from_key = from->pkey;
224
0
  if (from_key == NULL) {
225
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
226
0
    return 0;
227
0
  }
228
0
  const EC_GROUP *group = EC_KEY_get0_group(from_key);
229
0
  if (group == NULL) {
230
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
231
0
    return 0;
232
0
  }
233
0
  if (to->pkey == NULL) {
234
0
    to->pkey = EC_KEY_new();
235
0
    if (to->pkey == NULL) {
236
0
      return 0;
237
0
    }
238
0
  }
239
0
  return EC_KEY_set_group(to->pkey, group);
240
0
}
241
242
0
static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
243
0
  const EC_KEY *a_ec = a->pkey;
244
0
  const EC_KEY *b_ec = b->pkey;
245
0
  if (a_ec == NULL || b_ec == NULL) {
246
0
    return -2;
247
0
  }
248
0
  const EC_GROUP *group_a = EC_KEY_get0_group(a_ec),
249
0
                 *group_b = EC_KEY_get0_group(b_ec);
250
0
  if (group_a == NULL || group_b == NULL) {
251
0
    return -2;
252
0
  }
253
0
  if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) {
254
    // mismatch
255
0
    return 0;
256
0
  }
257
0
  return 1;
258
0
}
259
260
0
static void int_ec_free(EVP_PKEY *pkey) {
261
0
  EC_KEY_free(pkey->pkey);
262
0
  pkey->pkey = NULL;
263
0
}
264
265
0
static int eckey_opaque(const EVP_PKEY *pkey) {
266
0
  const EC_KEY *ec_key = pkey->pkey;
267
0
  return EC_KEY_is_opaque(ec_key);
268
0
}
269
270
const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
271
    EVP_PKEY_EC,
272
    // 1.2.840.10045.2.1
273
    {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01},
274
    7,
275
276
    &ec_pkey_meth,
277
278
    eckey_pub_decode,
279
    eckey_pub_encode,
280
    eckey_pub_cmp,
281
282
    eckey_priv_decode,
283
    eckey_priv_encode,
284
285
    /*set_priv_raw=*/NULL,
286
    /*set_pub_raw=*/NULL,
287
    /*get_priv_raw=*/NULL,
288
    /*get_pub_raw=*/NULL,
289
    eckey_set1_tls_encodedpoint,
290
    eckey_get1_tls_encodedpoint,
291
292
    eckey_opaque,
293
294
    int_ec_size,
295
    ec_bits,
296
297
    ec_missing_parameters,
298
    ec_copy_parameters,
299
    ec_cmp_parameters,
300
301
    int_ec_free,
302
};
303
304
0
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
305
0
  if (EVP_PKEY_assign_EC_KEY(pkey, key)) {
306
0
    EC_KEY_up_ref(key);
307
0
    return 1;
308
0
  }
309
0
  return 0;
310
0
}
311
312
0
int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
313
0
  evp_pkey_set_method(pkey, &ec_asn1_meth);
314
0
  pkey->pkey = key;
315
0
  return key != NULL;
316
0
}
317
318
0
EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) {
319
0
  if (pkey->type != EVP_PKEY_EC) {
320
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_EC_KEY_KEY);
321
0
    return NULL;
322
0
  }
323
0
  return pkey->pkey;
324
0
}
325
326
0
EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) {
327
0
  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
328
0
  if (ec_key != NULL) {
329
0
    EC_KEY_up_ref(ec_key);
330
0
  }
331
0
  return ec_key;
332
0
}