ec_key.c 19.0 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>
R
Rich Salz 已提交
67
#include <openssl/engine.h>
68 69

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

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

void EC_KEY_free(EC_KEY *r)
93 94
{
    int i;
95

96 97
    if (r == NULL)
        return;
98

99
    CRYPTO_atomic_add(&r->references, -1, &i, r->lock);
R
Rich Salz 已提交
100
    REF_PRINT_COUNT("EC_KEY", r);
101 102
    if (i > 0)
        return;
R
Rich Salz 已提交
103
    REF_ASSERT_ISNT(i < 0);
104

D
Dr. Stephen Henson 已提交
105
    if (r->meth->finish != NULL)
106 107
        r->meth->finish(r);

D
Dr. Stephen Henson 已提交
108
#ifndef OPENSSL_NO_ENGINE
R
Rich Salz 已提交
109
    ENGINE_finish(r->engine);
D
Dr. Stephen Henson 已提交
110 111
#endif

112 113 114
    if (r->group && r->group->meth->keyfinish)
        r->group->meth->keyfinish(r);

115
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
116
    CRYPTO_THREAD_lock_free(r->lock);
R
Rich Salz 已提交
117 118
    EC_GROUP_free(r->group);
    EC_POINT_free(r->pub_key);
R
Rich Salz 已提交
119
    BN_clear_free(r->priv_key);
120

R
Rich Salz 已提交
121
    OPENSSL_clear_free((void *)r, sizeof(EC_KEY));
122
}
123

124
EC_KEY *EC_KEY_copy(EC_KEY *dest, EC_KEY *src)
125 126 127 128 129
{
    if (dest == NULL || src == NULL) {
        ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }
D
Dr. Stephen Henson 已提交
130
    if (src->meth != dest->meth) {
D
Dr. Stephen Henson 已提交
131
        if (dest->meth->finish != NULL)
D
Dr. Stephen Henson 已提交
132
            dest->meth->finish(dest);
133 134
        if (dest->group && dest->group->meth->keyfinish)
            dest->group->meth->keyfinish(dest);
D
Dr. Stephen Henson 已提交
135
#ifndef OPENSSL_NO_ENGINE
R
Rich Salz 已提交
136
        if (ENGINE_finish(dest->engine) == 0)
D
Dr. Stephen Henson 已提交
137 138 139 140
            return 0;
        dest->engine = NULL;
#endif
    }
141
    /* copy the parameters */
D
Dr. Stephen Henson 已提交
142
    if (src->group != NULL) {
143 144
        const EC_METHOD *meth = EC_GROUP_method_of(src->group);
        /* clear the old group */
R
Rich Salz 已提交
145
        EC_GROUP_free(dest->group);
146 147 148 149 150
        dest->group = EC_GROUP_new(meth);
        if (dest->group == NULL)
            return NULL;
        if (!EC_GROUP_copy(dest->group, src->group))
            return NULL;
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

        /*  copy the public key */
        if (src->pub_key != NULL) {
            EC_POINT_free(dest->pub_key);
            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 */
        if (src->priv_key != NULL) {
            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;
            if (src->group->meth->keycopy
                && src->group->meth->keycopy(dest, src) == 0)
172 173 174 175
                return NULL;
        }
    }

176

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

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

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

198 199
    return dest;
}
200

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

205 206
    if (ret == NULL)
        return NULL;
207

208 209 210 211 212 213
    if (EC_KEY_copy(ret, ec_key) == NULL) {
        EC_KEY_free(ret);
        return NULL;
    }
    return ret;
}
214

B
Bodo Möller 已提交
215
int EC_KEY_up_ref(EC_KEY *r)
216
{
217 218 219 220
    int i;

    if (CRYPTO_atomic_add(&r->references, 1, &i, r->lock) <= 0)
        return 0;
R
Rich Salz 已提交
221 222 223

    REF_PRINT_COUNT("EC_KEY", r);
    REF_ASSERT_ISNT(i < 2);
224 225
    return ((i > 1) ? 1 : 0);
}
B
Bodo Möller 已提交
226

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

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

    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;

263 264
    order = EC_GROUP_get0_order(eckey->group);
    if (order == NULL)
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
        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 已提交
288
    if (eckey->pub_key == NULL)
289
        EC_POINT_free(pub_key);
R
Rich Salz 已提交
290
    if (eckey->priv_key != priv_key)
291
        BN_free(priv_key);
R
Rich Salz 已提交
292
    BN_CTX_free(ctx);
D
Dr. Stephen Henson 已提交
293 294 295 296 297 298 299
    return ok;
}

int ec_key_simple_generate_public_key(EC_KEY *eckey)
{
    return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL,
                        NULL, NULL);
300
}
301 302

int EC_KEY_check_key(const EC_KEY *eckey)
D
Dr. Stephen Henson 已提交
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
{
    if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (eckey->group->meth->keycheck == NULL) {
        ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }

    return eckey->group->meth->keycheck(eckey);
}

int ec_key_simple_check_key(const EC_KEY *eckey)
318 319 320 321 322 323
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    const BIGNUM *order = NULL;
    EC_POINT *point = NULL;

D
Dr. Stephen Henson 已提交
324
    if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
D
Dr. Stephen Henson 已提交
325
        ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
326 327 328 329
        return 0;
    }

    if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
D
Dr. Stephen Henson 已提交
330
        ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY);
331 332 333 334 335 336 337 338 339
        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 */
340
    if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
D
Dr. Stephen Henson 已提交
341
        ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
342 343 344 345 346
        goto err;
    }
    /* testing whether pub_key * order is the point at infinity */
    order = eckey->group->order;
    if (BN_is_zero(order)) {
D
Dr. Stephen Henson 已提交
347
        ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
348 349 350
        goto err;
    }
    if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
D
Dr. Stephen Henson 已提交
351
        ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB);
352 353 354
        goto err;
    }
    if (!EC_POINT_is_at_infinity(eckey->group, point)) {
D
Dr. Stephen Henson 已提交
355
        ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER);
356 357 358 359 360 361
        goto err;
    }
    /*
     * in case the priv_key is present : check if generator * priv_key ==
     * pub_key
     */
D
Dr. Stephen Henson 已提交
362
    if (eckey->priv_key != NULL) {
363
        if (BN_cmp(eckey->priv_key, order) >= 0) {
D
Dr. Stephen Henson 已提交
364
            ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER);
365 366 367 368
            goto err;
        }
        if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
                          NULL, NULL, ctx)) {
D
Dr. Stephen Henson 已提交
369
            ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB);
370 371 372
            goto err;
        }
        if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
D
Dr. Stephen Henson 已提交
373
            ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
374 375 376 377 378
            goto err;
        }
    }
    ok = 1;
 err:
R
Rich Salz 已提交
379
    BN_CTX_free(ctx);
R
Rich Salz 已提交
380
    EC_POINT_free(point);
D
Dr. Stephen Henson 已提交
381
    return ok;
382 383 384 385 386 387 388 389
}

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;
390 391 392 393
    int ok = 0;
#ifndef OPENSSL_NO_EC2M
    int tmp_nid, is_char_two = 0;
#endif
394

D
Dr. Stephen Henson 已提交
395
    if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
396 397 398 399 400
        ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
              ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }
    ctx = BN_CTX_new();
401
    if (ctx == NULL)
402
        return 0;
403

404
    BN_CTX_start(ctx);
405 406
    point = EC_POINT_new(key->group);

407
    if (point == NULL)
408 409
        goto err;

410 411
    tx = BN_CTX_get(ctx);
    ty = BN_CTX_get(ctx);
412 413
    if (ty == NULL)
        goto err;
414 415

#ifndef OPENSSL_NO_EC2M
416 417 418 419 420 421 422 423 424 425 426 427 428
    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
429
#endif
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
    {
        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:
459
    BN_CTX_end(ctx);
R
Rich Salz 已提交
460
    BN_CTX_free(ctx);
R
Rich Salz 已提交
461
    EC_POINT_free(point);
462 463 464
    return ok;

}
465

N
Nils Larsch 已提交
466
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
467 468 469
{
    return key->group;
}
N
Nils Larsch 已提交
470 471

int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
472
{
D
Dr. Stephen Henson 已提交
473
    if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0)
D
Dr. Stephen Henson 已提交
474
        return 0;
R
Rich Salz 已提交
475
    EC_GROUP_free(key->group);
476 477 478
    key->group = EC_GROUP_dup(group);
    return (key->group == NULL) ? 0 : 1;
}
N
Nils Larsch 已提交
479 480

const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
481 482 483
{
    return key->priv_key;
}
N
Nils Larsch 已提交
484 485

int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
486
{
487 488
    if (key->group == NULL || key->group->meth == NULL)
        return 0;
489 490
    if (key->group->meth->set_private != NULL
        && key->group->meth->set_private(key, priv_key) == 0)
491
        return 0;
D
Dr. Stephen Henson 已提交
492 493
    if (key->meth->set_private != NULL
        && key->meth->set_private(key, priv_key) == 0)
D
Dr. Stephen Henson 已提交
494
        return 0;
R
Rich Salz 已提交
495
    BN_clear_free(key->priv_key);
496 497 498
    key->priv_key = BN_dup(priv_key);
    return (key->priv_key == NULL) ? 0 : 1;
}
N
Nils Larsch 已提交
499 500

const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
501 502 503
{
    return key->pub_key;
}
N
Nils Larsch 已提交
504 505

int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
506
{
D
Dr. Stephen Henson 已提交
507 508
    if (key->meth->set_public != NULL
        && key->meth->set_public(key, pub_key) == 0)
D
Dr. Stephen Henson 已提交
509
        return 0;
R
Rich Salz 已提交
510
    EC_POINT_free(key->pub_key);
511 512 513
    key->pub_key = EC_POINT_dup(pub_key, key->group);
    return (key->pub_key == NULL) ? 0 : 1;
}
N
Nils Larsch 已提交
514 515

unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
516 517 518
{
    return key->enc_flag;
}
N
Nils Larsch 已提交
519 520

void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
521 522 523
{
    key->enc_flag = flags;
}
N
Nils Larsch 已提交
524 525

point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
526 527 528
{
    return key->conv_form;
}
N
Nils Larsch 已提交
529 530

void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
531 532 533 534 535
{
    key->conv_form = cform;
    if (key->group != NULL)
        EC_GROUP_set_point_conversion_form(key->group, cform);
}
N
Nils Larsch 已提交
536 537

void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
538 539 540 541
{
    if (key->group != NULL)
        EC_GROUP_set_asn1_flag(key->group, flag);
}
N
Nils Larsch 已提交
542 543

int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
544 545 546 547 548
{
    if (key->group == NULL)
        return 0;
    return EC_GROUP_precompute_mult(key->group, ctx);
}
549 550

int EC_KEY_get_flags(const EC_KEY *key)
551 552 553
{
    return key->flags;
}
554 555

void EC_KEY_set_flags(EC_KEY *key, int flags)
556 557 558
{
    key->flags |= flags;
}
559 560

void EC_KEY_clear_flags(EC_KEY *key, int flags)
561 562 563
{
    key->flags &= ~flags;
}
D
Dr. Stephen Henson 已提交
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

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;
582 583 584 585 586 587 588 589 590 591 592 593
    if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0)
        return 0;
    /*
     * Save the point conversion form.
     * For non-custom curves the first octet of the buffer (excluding
     * the last significant bit) contains the point conversion form.
     * EC_POINT_oct2point() has already performed sanity checking of
     * the buffer so we know it is valid.
     */
    if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0)
        key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01);
    return 1;
D
Dr. Stephen Henson 已提交
594
}
595 596 597 598 599

size_t EC_KEY_priv2oct(const EC_KEY *eckey, unsigned char *buf, size_t len)
{
    if (eckey->group == NULL || eckey->group->meth == NULL)
        return 0;
D
Dr. Stephen Henson 已提交
600 601 602 603 604 605 606 607 608 609 610 611
    if (eckey->group->meth->priv2oct == NULL) {
        ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }

    return eckey->group->meth->priv2oct(eckey, buf, len);
}

size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
                              unsigned char *buf, size_t len)
{
    size_t buf_len;
612

613
    buf_len = (EC_GROUP_order_bits(eckey->group) + 7) / 8;
614 615 616 617 618 619 620 621 622
    if (eckey->priv_key == NULL)
        return 0;
    if (buf == NULL)
        return buf_len;
    else if (len < buf_len)
        return 0;

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

D
Dr. Stephen Henson 已提交
623
    if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) {
D
Dr. Stephen Henson 已提交
624
        ECerr(EC_F_EC_KEY_SIMPLE_PRIV2OCT, EC_R_BUFFER_TOO_SMALL);
625 626 627 628 629 630 631 632 633 634
        return 0;
    }

    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;
D
Dr. Stephen Henson 已提交
635 636 637 638 639 640
    if (eckey->group->meth->oct2priv == NULL) {
        ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
        return 0;
    }
    return eckey->group->meth->oct2priv(eckey, buf, len);
}
641

D
Dr. Stephen Henson 已提交
642 643
int ec_key_simple_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len)
{
644 645 646
    if (eckey->priv_key == NULL)
        eckey->priv_key = BN_secure_new();
    if (eckey->priv_key == NULL) {
D
Dr. Stephen Henson 已提交
647
        ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_MALLOC_FAILURE);
648 649 650 651
        return 0;
    }
    eckey->priv_key = BN_bin2bn(buf, len, eckey->priv_key);
    if (eckey->priv_key == NULL) {
D
Dr. Stephen Henson 已提交
652
        ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB);
653 654 655 656
        return 0;
    }
    return 1;
}
D
Dr. Stephen Henson 已提交
657 658 659 660 661 662

size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf)
{
    size_t len;
    unsigned char *buf;
    len = EC_KEY_priv2oct(eckey, NULL, 0);
663 664
    if (len == 0)
        return 0;
D
Dr. Stephen Henson 已提交
665 666 667 668 669 670 671 672 673 674 675
    buf = OPENSSL_malloc(len);
    if (buf == NULL)
        return 0;
    len = EC_KEY_priv2oct(eckey, buf, len);
    if (len == 0) {
        OPENSSL_free(buf);
        return 0;
    }
    *pbuf = buf;
    return len;
}
D
Dr. Stephen Henson 已提交
676 677 678 679 680 681 682 683

int EC_KEY_can_sign(const EC_KEY *eckey)
{
    if (eckey->group == NULL || eckey->group->meth == NULL
        || (eckey->group->meth->flags & EC_FLAGS_NO_SIGN))
        return 0;
    return 1;
}