• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Written by Nils Larsch for the OpenSSL project. */
2 /* ====================================================================
3  * Copyright (c) 2000-2003 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    licensing@OpenSSL.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com). */
53 
54 #include <openssl/ec.h>
55 
56 #include <openssl/asn1.h>
57 #include <openssl/asn1t.h>
58 #include <openssl/bn.h>
59 #include <openssl/err.h>
60 #include <openssl/mem.h>
61 #include <openssl/obj.h>
62 
63 #include "internal.h"
64 
65 
66 typedef struct x9_62_fieldid_st {
67   ASN1_OBJECT *fieldType;
68   union {
69     char *ptr;
70     /* NID_X9_62_prime_field */
71     ASN1_INTEGER *prime;
72     /* anything else */
73     ASN1_TYPE *other;
74   } p;
75 } X9_62_FIELDID;
76 
77 ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
78 
79 ASN1_ADB(X9_62_FIELDID) = {
80   ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
81 } ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
82 
83 ASN1_SEQUENCE(X9_62_FIELDID) = {
84   ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
85   ASN1_ADB_OBJECT(X9_62_FIELDID)
86 } ASN1_SEQUENCE_END(X9_62_FIELDID);
87 
88 typedef struct x9_62_curve_st {
89   ASN1_OCTET_STRING *a;
90   ASN1_OCTET_STRING *b;
91   ASN1_BIT_STRING *seed;
92 } X9_62_CURVE;
93 
94 ASN1_SEQUENCE(X9_62_CURVE) = {
95   ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
96   ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
97   ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
98 } ASN1_SEQUENCE_END(X9_62_CURVE);
99 
100 typedef struct ec_parameters_st {
101   long version;
102   X9_62_FIELDID *fieldID;
103   X9_62_CURVE *curve;
104   ASN1_OCTET_STRING *base;
105   ASN1_INTEGER *order;
106   ASN1_INTEGER *cofactor;
107 } ECPARAMETERS;
108 
109 ASN1_SEQUENCE(ECPARAMETERS) = {
110     ASN1_SIMPLE(ECPARAMETERS, version, LONG),
111     ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
112     ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
113     ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
114     ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
115     ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
116 } ASN1_SEQUENCE_END(ECPARAMETERS);
117 
118 DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
119 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
120 
121 typedef struct ecpk_parameters_st {
122   int type;
123   union {
124     ASN1_OBJECT *named_curve;
125     ECPARAMETERS *parameters;
126   } value;
127 } ECPKPARAMETERS;
128 
129 /* SEC1 ECPrivateKey */
130 typedef struct ec_privatekey_st {
131   long version;
132   ASN1_OCTET_STRING *privateKey;
133   ECPKPARAMETERS *parameters;
134   ASN1_BIT_STRING *publicKey;
135 } EC_PRIVATEKEY;
136 
137 ASN1_CHOICE(ECPKPARAMETERS) = {
138     ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
139     ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
140 } ASN1_CHOICE_END(ECPKPARAMETERS);
141 
142 DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
143 DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS);
144 IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
145 
146 ASN1_SEQUENCE(EC_PRIVATEKEY) = {
147     ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
148     ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
149     ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
150     ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1),
151 } ASN1_SEQUENCE_END(EC_PRIVATEKEY);
152 
153 DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
154 DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY);
155 IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
156 
157 
ec_asn1_group2pkparameters(const EC_GROUP * group,ECPKPARAMETERS * params)158 ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
159                                            ECPKPARAMETERS *params) {
160   int ok = 0, nid;
161   ECPKPARAMETERS *ret = params;
162 
163   if (ret == NULL) {
164     ret = ECPKPARAMETERS_new();
165     if (ret == NULL) {
166       OPENSSL_PUT_ERROR(EC, ec_asn1_group2pkparameters, ERR_R_MALLOC_FAILURE);
167       return NULL;
168     }
169   } else {
170     if (ret->value.named_curve) {
171       ASN1_OBJECT_free(ret->value.named_curve);
172     }
173   }
174 
175   /* use the ASN.1 OID to describe the the elliptic curve parameters. */
176   nid = EC_GROUP_get_curve_name(group);
177   if (nid) {
178     ret->type = 0;
179     ret->value.named_curve = (ASN1_OBJECT*) OBJ_nid2obj(nid);
180     ok = ret->value.named_curve != NULL;
181   }
182 
183   if (!ok) {
184     ECPKPARAMETERS_free(ret);
185     return NULL;
186   }
187 
188   return ret;
189 }
190 
ec_asn1_pkparameters2group(const ECPKPARAMETERS * params)191 EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) {
192   EC_GROUP *ret = NULL;
193   int nid = NID_undef;
194 
195   if (params == NULL) {
196     OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group, EC_R_MISSING_PARAMETERS);
197     return NULL;
198   }
199 
200   if (params->type == 0) {
201     nid = OBJ_obj2nid(params->value.named_curve);
202   } else if (params->type == 1) {
203     /* We don't support arbitary curves so we attempt to recognise it from the
204      * group order. */
205     const ECPARAMETERS *ecparams = params->value.parameters;
206     unsigned i;
207     const struct built_in_curve *curve;
208 
209     for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
210       curve = &OPENSSL_built_in_curves[i];
211       const unsigned param_len = curve->data->param_len;
212       if (ecparams->order->length == param_len &&
213           memcmp(ecparams->order->data, &curve->data->data[param_len * 5],
214                  param_len) == 0) {
215         nid = curve->nid;
216         break;
217       }
218     }
219   }
220 
221   if (nid == NID_undef) {
222     OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group, EC_R_NON_NAMED_CURVE);
223     return NULL;
224   }
225 
226   ret = EC_GROUP_new_by_curve_name(nid);
227   if (ret == NULL) {
228     OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group,
229                       EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
230     return NULL;
231   }
232 
233   return ret;
234 }
235 
d2i_ECPKParameters(EC_GROUP ** groupp,const uint8_t ** inp,long len)236 static EC_GROUP *d2i_ECPKParameters(EC_GROUP **groupp, const uint8_t **inp,
237                                     long len) {
238   EC_GROUP *group = NULL;
239   ECPKPARAMETERS *params = NULL;
240 
241   params = d2i_ECPKPARAMETERS(NULL, inp, len);
242   if (params == NULL) {
243     OPENSSL_PUT_ERROR(EC, d2i_ECPKParameters, EC_R_D2I_ECPKPARAMETERS_FAILURE);
244     ECPKPARAMETERS_free(params);
245     return NULL;
246   }
247 
248   group = ec_asn1_pkparameters2group(params);
249   if (group == NULL) {
250     OPENSSL_PUT_ERROR(EC, d2i_ECPKParameters, EC_R_PKPARAMETERS2GROUP_FAILURE);
251     ECPKPARAMETERS_free(params);
252     return NULL;
253   }
254 
255   if (groupp && *groupp) {
256     EC_GROUP_free(*groupp);
257   }
258   if (groupp) {
259     *groupp = group;
260   }
261 
262   ECPKPARAMETERS_free(params);
263   return group;
264 }
265 
i2d_ECPKParameters(const EC_GROUP * group,uint8_t ** outp)266 static int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) {
267   int ret = 0;
268   ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(group, NULL);
269   if (tmp == NULL) {
270     OPENSSL_PUT_ERROR(EC, i2d_ECPKParameters, EC_R_GROUP2PKPARAMETERS_FAILURE);
271     return 0;
272   }
273   ret = i2d_ECPKPARAMETERS(tmp, outp);
274   if (ret == 0) {
275     OPENSSL_PUT_ERROR(EC, i2d_ECPKParameters, EC_R_I2D_ECPKPARAMETERS_FAILURE);
276     ECPKPARAMETERS_free(tmp);
277     return 0;
278   }
279   ECPKPARAMETERS_free(tmp);
280   return ret;
281 }
282 
d2i_ECPrivateKey(EC_KEY ** a,const uint8_t ** in,long len)283 EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
284   int ok = 0;
285   EC_KEY *ret = NULL;
286   EC_PRIVATEKEY *priv_key = NULL;
287 
288   priv_key = EC_PRIVATEKEY_new();
289   if (priv_key == NULL) {
290     OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_MALLOC_FAILURE);
291     return NULL;
292   }
293 
294   priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len);
295   if (priv_key == NULL) {
296     OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
297     EC_PRIVATEKEY_free(priv_key);
298     return NULL;
299   }
300 
301   if (a == NULL || *a == NULL) {
302     ret = EC_KEY_new();
303     if (ret == NULL) {
304       OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_MALLOC_FAILURE);
305       goto err;
306     }
307     if (a) {
308       *a = ret;
309     }
310   } else {
311     ret = *a;
312   }
313 
314   if (priv_key->parameters) {
315     if (ret->group) {
316       EC_GROUP_free(ret->group);
317     }
318     ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
319   }
320 
321   if (ret->group == NULL) {
322     OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
323     goto err;
324   }
325 
326   ret->version = priv_key->version;
327 
328   if (priv_key->privateKey) {
329     ret->priv_key =
330         BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
331                   M_ASN1_STRING_length(priv_key->privateKey), ret->priv_key);
332     if (ret->priv_key == NULL) {
333       OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_BN_LIB);
334       goto err;
335     }
336   } else {
337     OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, EC_R_MISSING_PRIVATE_KEY);
338     goto err;
339   }
340 
341   /* TODO(fork): loading the public key is silly. Why not calculate it? */
342   if (priv_key->publicKey) {
343     const uint8_t *pub_oct;
344     size_t pub_oct_len;
345 
346     if (ret->pub_key) {
347       EC_POINT_free(ret->pub_key);
348     }
349     ret->pub_key = EC_POINT_new(ret->group);
350     if (ret->pub_key == NULL) {
351       OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
352       goto err;
353     }
354     pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
355     pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
356     /* save the point conversion form */
357     ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
358     if (!EC_POINT_oct2point(ret->group, ret->pub_key, pub_oct, pub_oct_len,
359                             NULL)) {
360       OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
361       goto err;
362     }
363   }
364 
365   ok = 1;
366 
367 err:
368   if (!ok) {
369     if (ret) {
370       EC_KEY_free(ret);
371     }
372     ret = NULL;
373   }
374 
375   if (priv_key) {
376     EC_PRIVATEKEY_free(priv_key);
377   }
378 
379   return ret;
380 }
381 
i2d_ECPrivateKey(const EC_KEY * key,uint8_t ** outp)382 int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
383   int ret = 0, ok = 0;
384   uint8_t *buffer = NULL;
385   size_t buf_len = 0, tmp_len;
386   EC_PRIVATEKEY *priv_key = NULL;
387 
388   if (key == NULL || key->group == NULL || key->priv_key == NULL) {
389     OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_PASSED_NULL_PARAMETER);
390     goto err;
391   }
392 
393   priv_key = EC_PRIVATEKEY_new();
394   if (priv_key == NULL) {
395     OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
396     goto err;
397   }
398 
399   priv_key->version = key->version;
400 
401   buf_len = BN_num_bytes(key->priv_key);
402   buffer = OPENSSL_malloc(buf_len);
403   if (buffer == NULL) {
404     OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
405     goto err;
406   }
407 
408   if (!BN_bn2bin(key->priv_key, buffer)) {
409     OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_BN_LIB);
410     goto err;
411   }
412 
413   if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
414     OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_ASN1_LIB);
415     goto err;
416   }
417 
418   /* TODO(fork): replace this flexibility with key sensible default? */
419   if (!(key->enc_flag & EC_PKEY_NO_PARAMETERS)) {
420     if ((priv_key->parameters = ec_asn1_group2pkparameters(
421              key->group, priv_key->parameters)) == NULL) {
422       OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_EC_LIB);
423       goto err;
424     }
425   }
426 
427   /* TODO(fork): replace this flexibility with key sensible default? */
428   if (!(key->enc_flag & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
429     priv_key->publicKey = M_ASN1_BIT_STRING_new();
430     if (priv_key->publicKey == NULL) {
431       OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
432       goto err;
433     }
434 
435     tmp_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL,
436                                  0, NULL);
437 
438     if (tmp_len > buf_len) {
439       uint8_t *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
440       if (!tmp_buffer) {
441         OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
442         goto err;
443       }
444       buffer = tmp_buffer;
445       buf_len = tmp_len;
446     }
447 
448     if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, buffer,
449                             buf_len, NULL)) {
450       OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_EC_LIB);
451       goto err;
452     }
453 
454     priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
455     priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
456     if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
457       OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_ASN1_LIB);
458       goto err;
459     }
460   }
461 
462   ret = i2d_EC_PRIVATEKEY(priv_key, outp);
463   if (ret == 0) {
464     OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_EC_LIB);
465     goto err;
466   }
467   ok = 1;
468 
469 err:
470   if (buffer) {
471     OPENSSL_free(buffer);
472   }
473   if (priv_key) {
474     EC_PRIVATEKEY_free(priv_key);
475   }
476   return (ok ? ret : 0);
477 }
478 
i2d_ECParameters(const EC_KEY * key,uint8_t ** outp)479 int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
480   if (key == NULL) {
481     OPENSSL_PUT_ERROR(EC, i2d_ECParameters, ERR_R_PASSED_NULL_PARAMETER);
482     return 0;
483   }
484   return i2d_ECPKParameters(key->group, outp);
485 }
486 
d2i_ECParameters(EC_KEY ** key,const uint8_t ** inp,long len)487 EC_KEY *d2i_ECParameters(EC_KEY **key, const uint8_t **inp, long len) {
488   EC_KEY *ret;
489 
490   if (inp == NULL || *inp == NULL) {
491     OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_PASSED_NULL_PARAMETER);
492     return NULL;
493   }
494 
495   if (key == NULL || *key == NULL) {
496     ret = EC_KEY_new();
497     if (ret == NULL) {
498       OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_MALLOC_FAILURE);
499       return NULL;
500     }
501     if (key) {
502       *key = ret;
503     }
504   } else {
505     ret = *key;
506   }
507 
508   if (!d2i_ECPKParameters(&ret->group, inp, len)) {
509     OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_EC_LIB);
510     return NULL;
511   }
512 
513   return ret;
514 }
515 
o2i_ECPublicKey(EC_KEY ** keyp,const uint8_t ** inp,long len)516 EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
517   EC_KEY *ret = NULL;
518 
519   if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) {
520     OPENSSL_PUT_ERROR(EC, o2i_ECPublicKey, ERR_R_PASSED_NULL_PARAMETER);
521     return 0;
522   }
523   ret = *keyp;
524   if (ret->pub_key == NULL &&
525       (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
526     OPENSSL_PUT_ERROR(EC, o2i_ECPublicKey, ERR_R_MALLOC_FAILURE);
527     return 0;
528   }
529   if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) {
530     OPENSSL_PUT_ERROR(EC, o2i_ECPublicKey, ERR_R_EC_LIB);
531     return 0;
532   }
533   /* save the point conversion form */
534   ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
535   *inp += len;
536   return ret;
537 }
538 
i2o_ECPublicKey(const EC_KEY * key,uint8_t ** outp)539 int i2o_ECPublicKey(const EC_KEY *key, uint8_t **outp) {
540   size_t buf_len = 0;
541   int new_buffer = 0;
542 
543   if (key == NULL) {
544     OPENSSL_PUT_ERROR(EC, i2o_ECPublicKey, ERR_R_PASSED_NULL_PARAMETER);
545     return 0;
546   }
547 
548   buf_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL,
549                                0, NULL);
550 
551   if (outp == NULL || buf_len == 0) {
552     /* out == NULL => just return the length of the octet string */
553     return buf_len;
554   }
555 
556   if (*outp == NULL) {
557     *outp = OPENSSL_malloc(buf_len);
558     if (*outp == NULL) {
559       OPENSSL_PUT_ERROR(EC, i2o_ECPublicKey, ERR_R_MALLOC_FAILURE);
560       return 0;
561     }
562     new_buffer = 1;
563   }
564   if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, *outp,
565                           buf_len, NULL)) {
566     OPENSSL_PUT_ERROR(EC, i2o_ECPublicKey, ERR_R_EC_LIB);
567     if (new_buffer) {
568       OPENSSL_free(*outp);
569       *outp = NULL;
570     }
571     return 0;
572   }
573 
574   if (!new_buffer) {
575     *outp += buf_len;
576   }
577   return buf_len;
578 }
579