ec_key.c 16.4 KB
Newer Older
1 2 3 4
/*
 * Written by Nils Larsch for the OpenSSL project.
 */
/* ====================================================================
N
Nils Larsch 已提交
5
 * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
6 7 8 9 10 11
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    openssl-core@openssl.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */
B
Bodo Möller 已提交
57 58
/* ====================================================================
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
59
 * Portions originally developed by SUN MICROSYSTEMS, INC., and
B
Bodo Möller 已提交
60 61
 * contributed to the OpenSSL project.
 */
62

D
David Woodhouse 已提交
63
#include <internal/cryptlib.h>
64
#include <string.h>
65 66
#include "ec_lcl.h"
#include <openssl/err.h>
B
Ben Laurie 已提交
67
#ifndef OPENSSL_NO_ENGINE
D
Dr. Stephen Henson 已提交
68 69
# include <openssl/engine.h>
#endif
70 71

EC_KEY *EC_KEY_new(void)
72
{
D
Dr. Stephen Henson 已提交
73
    return EC_KEY_new_method(NULL);
74
}
75

N
Nils Larsch 已提交
76
EC_KEY *EC_KEY_new_by_curve_name(int nid)
77 78 79 80 81 82 83 84 85
{
    EC_KEY *ret = EC_KEY_new();
    if (ret == NULL)
        return NULL;
    ret->group = EC_GROUP_new_by_curve_name(nid);
    if (ret->group == NULL) {
        EC_KEY_free(ret);
        return NULL;
    }
D
Dr. Stephen Henson 已提交
86 87
    if (ret->meth->set_group != NULL
        && ret->meth->set_group(ret, ret->group) == 0) {
D
Dr. Stephen Henson 已提交
88 89 90
        EC_KEY_free(ret);
        return NULL;
    }
91 92
    return ret;
}
93 94

void EC_KEY_free(EC_KEY *r)
95 96
{
    int i;
97

98 99
    if (r == NULL)
        return;
100

101
    i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
102
#ifdef REF_PRINT
103
    REF_PRINT("EC_KEY", r);
104
#endif
105 106
    if (i > 0)
        return;
107
#ifdef REF_CHECK
108 109 110 111
    if (i < 0) {
        fprintf(stderr, "EC_KEY_free, bad reference count\n");
        abort();
    }
112 113
#endif

D
Dr. Stephen Henson 已提交
114
    if (r->meth->finish != NULL)
115 116
        r->meth->finish(r);

D
Dr. Stephen Henson 已提交
117
#ifndef OPENSSL_NO_ENGINE
D
Dr. Stephen Henson 已提交
118
    if (r->engine != NULL)
D
Dr. Stephen Henson 已提交
119 120 121
        ENGINE_finish(r->engine);
#endif

122
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
R
Rich Salz 已提交
123 124
    EC_GROUP_free(r->group);
    EC_POINT_free(r->pub_key);
R
Rich Salz 已提交
125
    BN_clear_free(r->priv_key);
126

R
Rich Salz 已提交
127
    OPENSSL_clear_free((void *)r, sizeof(EC_KEY));
128
}
129

130
EC_KEY *EC_KEY_copy(EC_KEY *dest, EC_KEY *src)
131 132 133 134 135
{
    if (dest == NULL || src == NULL) {
        ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }
D
Dr. Stephen Henson 已提交
136
    if (src->meth != dest->meth) {
D
Dr. Stephen Henson 已提交
137
        if (dest->meth->finish != NULL)
D
Dr. Stephen Henson 已提交
138 139
            dest->meth->finish(dest);
#ifndef OPENSSL_NO_ENGINE
D
Dr. Stephen Henson 已提交
140
        if (dest->engine != NULL && ENGINE_finish(dest->engine) == 0)
D
Dr. Stephen Henson 已提交
141 142 143 144
            return 0;
        dest->engine = NULL;
#endif
    }
145
    /* copy the parameters */
D
Dr. Stephen Henson 已提交
146
    if (src->group != NULL) {
147 148
        const EC_METHOD *meth = EC_GROUP_method_of(src->group);
        /* clear the old group */
R
Rich Salz 已提交
149
        EC_GROUP_free(dest->group);
150 151 152 153 154 155 156
        dest->group = EC_GROUP_new(meth);
        if (dest->group == NULL)
            return NULL;
        if (!EC_GROUP_copy(dest->group, src->group))
            return NULL;
    }
    /*  copy the public key */
D
Dr. Stephen Henson 已提交
157
    if (src->pub_key != NULL && src->group != NULL) {
R
Rich Salz 已提交
158
        EC_POINT_free(dest->pub_key);
159 160 161 162 163 164 165
        dest->pub_key = EC_POINT_new(src->group);
        if (dest->pub_key == NULL)
            return NULL;
        if (!EC_POINT_copy(dest->pub_key, src->pub_key))
            return NULL;
    }
    /* copy the private key */
D
Dr. Stephen Henson 已提交
166
    if (src->priv_key != NULL) {
167 168 169 170 171 172 173 174 175 176 177 178 179 180
        if (dest->priv_key == NULL) {
            dest->priv_key = BN_new();
            if (dest->priv_key == NULL)
                return NULL;
        }
        if (!BN_copy(dest->priv_key, src->priv_key))
            return NULL;
    }

    /* copy the rest */
    dest->enc_flag = src->enc_flag;
    dest->conv_form = src->conv_form;
    dest->version = src->version;
    dest->flags = src->flags;
181 182 183
    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
                            &dest->ex_data, &src->ex_data))
        return NULL;
184

D
Dr. Stephen Henson 已提交
185 186
    if (src->meth != dest->meth) {
#ifndef OPENSSL_NO_ENGINE
D
Dr. Stephen Henson 已提交
187 188
        if (src->engine != NULL && ENGINE_init(src->engine) == 0)
            return NULL;
D
Dr. Stephen Henson 已提交
189 190 191 192 193
        dest->engine = src->engine;
#endif
        dest->meth = src->meth;
    }

D
Dr. Stephen Henson 已提交
194 195
    if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0)
        return NULL;
D
Dr. Stephen Henson 已提交
196

197 198
    return dest;
}
199

200
EC_KEY *EC_KEY_dup(EC_KEY *ec_key)
201
{
D
Dr. Stephen Henson 已提交
202
    EC_KEY *ret = EC_KEY_new_method(ec_key->engine);
203

204 205 206 207 208 209 210 211
    if (ret == NULL)
        return NULL;
    if (EC_KEY_copy(ret, ec_key) == NULL) {
        EC_KEY_free(ret);
        return NULL;
    }
    return ret;
}
212

B
Bodo Möller 已提交
213
int EC_KEY_up_ref(EC_KEY *r)
214 215
{
    int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
B
Bodo Möller 已提交
216
#ifdef REF_PRINT
217
    REF_PRINT("EC_KEY", r);
B
Bodo Möller 已提交
218 219
#endif
#ifdef REF_CHECK
220 221 222 223
    if (i < 2) {
        fprintf(stderr, "EC_KEY_up, bad reference count\n");
        abort();
    }
B
Bodo Möller 已提交
224
#endif
225 226
    return ((i > 1) ? 1 : 0);
}
B
Bodo Möller 已提交
227

228
int EC_KEY_generate_key(EC_KEY *eckey)
229
{
D
Dr. Stephen Henson 已提交
230
    if (eckey == NULL || eckey->group == NULL) {
231 232 233
        ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
D
Dr. Stephen Henson 已提交
234
    if (eckey->meth->keygen != NULL)
D
Dr. Stephen Henson 已提交
235 236 237 238 239 240 241 242 243
        return eckey->meth->keygen(eckey);
    ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED);
    return 0;
}

int ossl_ec_key_gen(EC_KEY *eckey)
{
    int ok = 0;
    BN_CTX *ctx = NULL;
244 245
    BIGNUM *priv_key = NULL;
    const BIGNUM *order = NULL;
D
Dr. Stephen Henson 已提交
246
    EC_POINT *pub_key = NULL;
247 248 249 250 251 252 253 254 255 256 257

    if ((ctx = BN_CTX_new()) == NULL)
        goto err;

    if (eckey->priv_key == NULL) {
        priv_key = BN_new();
        if (priv_key == NULL)
            goto err;
    } else
        priv_key = eckey->priv_key;

258 259
    order = EC_GROUP_get0_order(eckey->group);
    if (order == NULL)
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
        goto err;

    do
        if (!BN_rand_range(priv_key, order))
            goto err;
    while (BN_is_zero(priv_key)) ;

    if (eckey->pub_key == NULL) {
        pub_key = EC_POINT_new(eckey->group);
        if (pub_key == NULL)
            goto err;
    } else
        pub_key = eckey->pub_key;

    if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
        goto err;

    eckey->priv_key = priv_key;
    eckey->pub_key = pub_key;

    ok = 1;

 err:
R
Rich Salz 已提交
283
    if (eckey->pub_key == NULL)
284
        EC_POINT_free(pub_key);
R
Rich Salz 已提交
285
    if (eckey->priv_key != priv_key)
286
        BN_free(priv_key);
R
Rich Salz 已提交
287
    BN_CTX_free(ctx);
288 289
    return (ok);
}
290 291

int EC_KEY_check_key(const EC_KEY *eckey)
292 293 294 295 296 297
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    const BIGNUM *order = NULL;
    EC_POINT *point = NULL;

D
Dr. Stephen Henson 已提交
298
    if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
        ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
        goto err;
    }

    if ((ctx = BN_CTX_new()) == NULL)
        goto err;
    if ((point = EC_POINT_new(eckey->group)) == NULL)
        goto err;

    /* testing whether the pub_key is on the elliptic curve */
314
    if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
        ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
        goto err;
    }
    /* testing whether pub_key * order is the point at infinity */
    order = eckey->group->order;
    if (BN_is_zero(order)) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
        goto err;
    }
    if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
        goto err;
    }
    if (!EC_POINT_is_at_infinity(eckey->group, point)) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
        goto err;
    }
    /*
     * in case the priv_key is present : check if generator * priv_key ==
     * pub_key
     */
D
Dr. Stephen Henson 已提交
336
    if (eckey->priv_key != NULL) {
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
        if (BN_cmp(eckey->priv_key, order) >= 0) {
            ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
            goto err;
        }
        if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
                          NULL, NULL, ctx)) {
            ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
            goto err;
        }
        if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
            ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
            goto err;
        }
    }
    ok = 1;
 err:
R
Rich Salz 已提交
353
    BN_CTX_free(ctx);
R
Rich Salz 已提交
354
    EC_POINT_free(point);
355 356 357 358 359 360 361 362 363
    return (ok);
}

int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
                                             BIGNUM *y)
{
    BN_CTX *ctx = NULL;
    BIGNUM *tx, *ty;
    EC_POINT *point = NULL;
364 365 366 367
    int ok = 0;
#ifndef OPENSSL_NO_EC2M
    int tmp_nid, is_char_two = 0;
#endif
368

D
Dr. Stephen Henson 已提交
369
    if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
370 371 372 373 374
        ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
              ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
    ctx = BN_CTX_new();
375
    if (ctx == NULL)
376 377 378 379
        goto err;

    point = EC_POINT_new(key->group);

380
    if (point == NULL)
381 382
        goto err;

383 384
    tx = BN_CTX_get(ctx);
    ty = BN_CTX_get(ctx);
385 386
    if (ty == NULL)
        goto err;
387 388

#ifndef OPENSSL_NO_EC2M
389 390 391 392 393 394 395 396 397 398 399 400 401
    tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));

    if (tmp_nid == NID_X9_62_characteristic_two_field)
        is_char_two = 1;

    if (is_char_two) {
        if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
                                                  x, y, ctx))
            goto err;
        if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
                                                  tx, ty, ctx))
            goto err;
    } else
402
#endif
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
    {
        if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
                                                 x, y, ctx))
            goto err;
        if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
                                                 tx, ty, ctx))
            goto err;
    }
    /*
     * Check if retrieved coordinates match originals and are less than field
     * order: if not values are out of range.
     */
    if (BN_cmp(x, tx) || BN_cmp(y, ty)
        || (BN_cmp(x, key->group->field) >= 0)
        || (BN_cmp(y, key->group->field) >= 0)) {
        ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
              EC_R_COORDINATES_OUT_OF_RANGE);
        goto err;
    }

    if (!EC_KEY_set_public_key(key, point))
        goto err;

    if (EC_KEY_check_key(key) == 0)
        goto err;

    ok = 1;

 err:
R
Rich Salz 已提交
432
    BN_CTX_free(ctx);
R
Rich Salz 已提交
433
    EC_POINT_free(point);
434 435 436
    return ok;

}
437

N
Nils Larsch 已提交
438
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
439 440 441
{
    return key->group;
}
N
Nils Larsch 已提交
442 443

int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
444
{
D
Dr. Stephen Henson 已提交
445
    if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0)
D
Dr. Stephen Henson 已提交
446
        return 0;
R
Rich Salz 已提交
447
    EC_GROUP_free(key->group);
448 449 450
    key->group = EC_GROUP_dup(group);
    return (key->group == NULL) ? 0 : 1;
}
N
Nils Larsch 已提交
451 452

const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
453 454 455
{
    return key->priv_key;
}
N
Nils Larsch 已提交
456 457

int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
458
{
D
Dr. Stephen Henson 已提交
459 460
    if (key->meth->set_private != NULL
        && key->meth->set_private(key, priv_key) == 0)
D
Dr. Stephen Henson 已提交
461
        return 0;
R
Rich Salz 已提交
462
    BN_clear_free(key->priv_key);
463 464 465
    key->priv_key = BN_dup(priv_key);
    return (key->priv_key == NULL) ? 0 : 1;
}
N
Nils Larsch 已提交
466 467

const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
468 469 470
{
    return key->pub_key;
}
N
Nils Larsch 已提交
471 472

int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
473
{
D
Dr. Stephen Henson 已提交
474 475
    if (key->meth->set_public != NULL
        && key->meth->set_public(key, pub_key) == 0)
D
Dr. Stephen Henson 已提交
476
        return 0;
R
Rich Salz 已提交
477
    EC_POINT_free(key->pub_key);
478 479 480
    key->pub_key = EC_POINT_dup(pub_key, key->group);
    return (key->pub_key == NULL) ? 0 : 1;
}
N
Nils Larsch 已提交
481 482

unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
483 484 485
{
    return key->enc_flag;
}
N
Nils Larsch 已提交
486 487

void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
488 489 490
{
    key->enc_flag = flags;
}
N
Nils Larsch 已提交
491 492

point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
493 494 495
{
    return key->conv_form;
}
N
Nils Larsch 已提交
496 497

void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
498 499 500 501 502
{
    key->conv_form = cform;
    if (key->group != NULL)
        EC_GROUP_set_point_conversion_form(key->group, cform);
}
N
Nils Larsch 已提交
503 504

void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
505 506 507 508
{
    if (key->group != NULL)
        EC_GROUP_set_asn1_flag(key->group, flag);
}
N
Nils Larsch 已提交
509 510

int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
511 512 513 514 515
{
    if (key->group == NULL)
        return 0;
    return EC_GROUP_precompute_mult(key->group, ctx);
}
516 517

int EC_KEY_get_flags(const EC_KEY *key)
518 519 520
{
    return key->flags;
}
521 522

void EC_KEY_set_flags(EC_KEY *key, int flags)
523 524 525
{
    key->flags |= flags;
}
526 527

void EC_KEY_clear_flags(EC_KEY *key, int flags)
528 529 530
{
    key->flags &= ~flags;
}
D
Dr. Stephen Henson 已提交
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550

size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
                        unsigned char **pbuf, BN_CTX *ctx)
{
    if (key == NULL || key->pub_key == NULL || key->group == NULL)
        return 0;
    return EC_POINT_point2buf(key->group, key->pub_key, form, pbuf, ctx);
}

int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
                   BN_CTX *ctx)
{
    if (key == NULL || key->group == NULL)
        return 0;
    if (key->pub_key == NULL)
        key->pub_key = EC_POINT_new(key->group);
    if (key->pub_key == NULL)
        return 0;
    return EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx);
}
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570

size_t EC_KEY_priv2oct(const EC_KEY *eckey, unsigned char *buf, size_t len)
{
    size_t buf_len, bn_len;
    if (eckey->group == NULL || eckey->group->meth == NULL)
        return 0;

    buf_len = (EC_GROUP_get_degree(eckey->group) + 7) / 8;
    if (eckey->priv_key == NULL)
        return 0;
    if (buf == NULL)
        return buf_len;
    else if (len < buf_len)
        return 0;

    bn_len = (size_t)BN_num_bytes(eckey->priv_key);

    /* Octetstring may need leading zeros if BN is to short */

    if (bn_len > buf_len) {
571
        ECerr(EC_F_EC_KEY_PRIV2OCT, EC_R_BUFFER_TOO_SMALL);
572 573 574 575
        return 0;
    }

    if (!BN_bn2bin(eckey->priv_key, buf + buf_len - bn_len)) {
576
        ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_BN_LIB);
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
        return 0;
    }

    if (buf_len - bn_len > 0)
        memset(buf, 0, buf_len - bn_len);

    return buf_len;
}

int EC_KEY_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len)
{
    if (eckey->group == NULL || eckey->group->meth == NULL)
        return 0;

    if (eckey->priv_key == NULL)
        eckey->priv_key = BN_secure_new();
    if (eckey->priv_key == NULL) {
594
        ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_MALLOC_FAILURE);
595 596 597 598
        return 0;
    }
    eckey->priv_key = BN_bin2bn(buf, len, eckey->priv_key);
    if (eckey->priv_key == NULL) {
599
        ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_BN_LIB);
600 601 602 603
        return 0;
    }
    return 1;
}