jdk/src/share/native/sun/security/ec/ec.c
changeset 3492 e549cea58864
child 3636 b80fdcc0b0d5
equal deleted inserted replaced
3480:c197e38bf15a 3492:e549cea58864
       
     1 /* *********************************************************************
       
     2  *
       
     3  * Sun elects to have this file available under and governed by the
       
     4  * Mozilla Public License Version 1.1 ("MPL") (see
       
     5  * http://www.mozilla.org/MPL/ for full license text). For the avoidance
       
     6  * of doubt and subject to the following, Sun also elects to allow
       
     7  * licensees to use this file under the MPL, the GNU General Public
       
     8  * License version 2 only or the Lesser General Public License version
       
     9  * 2.1 only. Any references to the "GNU General Public License version 2
       
    10  * or later" or "GPL" in the following shall be construed to mean the
       
    11  * GNU General Public License version 2 only. Any references to the "GNU
       
    12  * Lesser General Public License version 2.1 or later" or "LGPL" in the
       
    13  * following shall be construed to mean the GNU Lesser General Public
       
    14  * License version 2.1 only. However, the following notice accompanied
       
    15  * the original version of this file:
       
    16  *
       
    17  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       
    18  *
       
    19  * The contents of this file are subject to the Mozilla Public License Version
       
    20  * 1.1 (the "License"); you may not use this file except in compliance with
       
    21  * the License. You may obtain a copy of the License at
       
    22  * http://www.mozilla.org/MPL/
       
    23  *
       
    24  * Software distributed under the License is distributed on an "AS IS" basis,
       
    25  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
       
    26  * for the specific language governing rights and limitations under the
       
    27  * License.
       
    28  *
       
    29  * The Original Code is the Elliptic Curve Cryptography library.
       
    30  *
       
    31  * The Initial Developer of the Original Code is
       
    32  * Sun Microsystems, Inc.
       
    33  * Portions created by the Initial Developer are Copyright (C) 2003
       
    34  * the Initial Developer. All Rights Reserved.
       
    35  *
       
    36  * Contributor(s):
       
    37  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
       
    38  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
       
    39  *
       
    40  * Alternatively, the contents of this file may be used under the terms of
       
    41  * either the GNU General Public License Version 2 or later (the "GPL"), or
       
    42  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
       
    43  * in which case the provisions of the GPL or the LGPL are applicable instead
       
    44  * of those above. If you wish to allow use of your version of this file only
       
    45  * under the terms of either the GPL or the LGPL, and not to allow others to
       
    46  * use your version of this file under the terms of the MPL, indicate your
       
    47  * decision by deleting the provisions above and replace them with the notice
       
    48  * and other provisions required by the GPL or the LGPL. If you do not delete
       
    49  * the provisions above, a recipient may use your version of this file under
       
    50  * the terms of any one of the MPL, the GPL or the LGPL.
       
    51  *
       
    52  *********************************************************************** */
       
    53 /*
       
    54  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
       
    55  * Use is subject to license terms.
       
    56  */
       
    57 
       
    58 #pragma ident   "%Z%%M% %I%     %E% SMI"
       
    59 
       
    60 #include "mplogic.h"
       
    61 #include "ec.h"
       
    62 #include "ecl.h"
       
    63 
       
    64 #include <sys/types.h>
       
    65 #ifndef _KERNEL
       
    66 #include <stdlib.h>
       
    67 #include <string.h>
       
    68 
       
    69 #ifndef _WIN32
       
    70 #include <strings.h>
       
    71 #endif /* _WIN32 */
       
    72 
       
    73 #endif
       
    74 #include "ecl-exp.h"
       
    75 #include "mpi.h"
       
    76 #include "ecc_impl.h"
       
    77 
       
    78 #ifdef _KERNEL
       
    79 #define PORT_ZFree(p, l)                bzero((p), (l)); kmem_free((p), (l))
       
    80 #else
       
    81 #ifndef _WIN32
       
    82 #define PORT_ZFree(p, l)                bzero((p), (l)); free((p))
       
    83 #else
       
    84 #define PORT_ZFree(p, l)                memset((p), 0, (l)); free((p))
       
    85 #endif /* _WIN32 */
       
    86 #endif
       
    87 
       
    88 /*
       
    89  * Returns true if pointP is the point at infinity, false otherwise
       
    90  */
       
    91 PRBool
       
    92 ec_point_at_infinity(SECItem *pointP)
       
    93 {
       
    94     unsigned int i;
       
    95 
       
    96     for (i = 1; i < pointP->len; i++) {
       
    97         if (pointP->data[i] != 0x00) return PR_FALSE;
       
    98     }
       
    99 
       
   100     return PR_TRUE;
       
   101 }
       
   102 
       
   103 /*
       
   104  * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
       
   105  * the curve whose parameters are encoded in params with base point G.
       
   106  */
       
   107 SECStatus
       
   108 ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
       
   109              const SECItem *pointP, SECItem *pointQ, int kmflag)
       
   110 {
       
   111     mp_int Px, Py, Qx, Qy;
       
   112     mp_int Gx, Gy, order, irreducible, a, b;
       
   113 #if 0 /* currently don't support non-named curves */
       
   114     unsigned int irr_arr[5];
       
   115 #endif
       
   116     ECGroup *group = NULL;
       
   117     SECStatus rv = SECFailure;
       
   118     mp_err err = MP_OKAY;
       
   119     int len;
       
   120 
       
   121 #if EC_DEBUG
       
   122     int i;
       
   123     char mpstr[256];
       
   124 
       
   125     printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
       
   126     for (i = 0; i < params->DEREncoding.len; i++)
       
   127             printf("%02x:", params->DEREncoding.data[i]);
       
   128     printf("\n");
       
   129 
       
   130         if (k1 != NULL) {
       
   131                 mp_tohex(k1, mpstr);
       
   132                 printf("ec_points_mul: scalar k1: %s\n", mpstr);
       
   133                 mp_todecimal(k1, mpstr);
       
   134                 printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
       
   135         }
       
   136 
       
   137         if (k2 != NULL) {
       
   138                 mp_tohex(k2, mpstr);
       
   139                 printf("ec_points_mul: scalar k2: %s\n", mpstr);
       
   140                 mp_todecimal(k2, mpstr);
       
   141                 printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
       
   142         }
       
   143 
       
   144         if (pointP != NULL) {
       
   145                 printf("ec_points_mul: pointP [len=%d]:", pointP->len);
       
   146                 for (i = 0; i < pointP->len; i++)
       
   147                         printf("%02x:", pointP->data[i]);
       
   148                 printf("\n");
       
   149         }
       
   150 #endif
       
   151 
       
   152         /* NOTE: We only support uncompressed points for now */
       
   153         len = (params->fieldID.size + 7) >> 3;
       
   154         if (pointP != NULL) {
       
   155                 if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
       
   156                         (pointP->len != (2 * len + 1))) {
       
   157                         return SECFailure;
       
   158                 };
       
   159         }
       
   160 
       
   161         MP_DIGITS(&Px) = 0;
       
   162         MP_DIGITS(&Py) = 0;
       
   163         MP_DIGITS(&Qx) = 0;
       
   164         MP_DIGITS(&Qy) = 0;
       
   165         MP_DIGITS(&Gx) = 0;
       
   166         MP_DIGITS(&Gy) = 0;
       
   167         MP_DIGITS(&order) = 0;
       
   168         MP_DIGITS(&irreducible) = 0;
       
   169         MP_DIGITS(&a) = 0;
       
   170         MP_DIGITS(&b) = 0;
       
   171         CHECK_MPI_OK( mp_init(&Px, kmflag) );
       
   172         CHECK_MPI_OK( mp_init(&Py, kmflag) );
       
   173         CHECK_MPI_OK( mp_init(&Qx, kmflag) );
       
   174         CHECK_MPI_OK( mp_init(&Qy, kmflag) );
       
   175         CHECK_MPI_OK( mp_init(&Gx, kmflag) );
       
   176         CHECK_MPI_OK( mp_init(&Gy, kmflag) );
       
   177         CHECK_MPI_OK( mp_init(&order, kmflag) );
       
   178         CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
       
   179         CHECK_MPI_OK( mp_init(&a, kmflag) );
       
   180         CHECK_MPI_OK( mp_init(&b, kmflag) );
       
   181 
       
   182         if ((k2 != NULL) && (pointP != NULL)) {
       
   183                 /* Initialize Px and Py */
       
   184                 CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
       
   185                 CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
       
   186         }
       
   187 
       
   188         /* construct from named params, if possible */
       
   189         if (params->name != ECCurve_noName) {
       
   190                 group = ECGroup_fromName(params->name, kmflag);
       
   191         }
       
   192 
       
   193 #if 0 /* currently don't support non-named curves */
       
   194         if (group == NULL) {
       
   195                 /* Set up mp_ints containing the curve coefficients */
       
   196                 CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1,
       
   197                                                                                   (mp_size) len) );
       
   198                 CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len,
       
   199                                                                                   (mp_size) len) );
       
   200                 SECITEM_TO_MPINT( params->order, &order );
       
   201                 SECITEM_TO_MPINT( params->curve.a, &a );
       
   202                 SECITEM_TO_MPINT( params->curve.b, &b );
       
   203                 if (params->fieldID.type == ec_field_GFp) {
       
   204                         SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
       
   205                         group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
       
   206                 } else {
       
   207                         SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
       
   208                         irr_arr[0] = params->fieldID.size;
       
   209                         irr_arr[1] = params->fieldID.k1;
       
   210                         irr_arr[2] = params->fieldID.k2;
       
   211                         irr_arr[3] = params->fieldID.k3;
       
   212                         irr_arr[4] = 0;
       
   213                         group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
       
   214                 }
       
   215         }
       
   216 #endif
       
   217         if (group == NULL)
       
   218                 goto cleanup;
       
   219 
       
   220         if ((k2 != NULL) && (pointP != NULL)) {
       
   221                 CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
       
   222         } else {
       
   223                 CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
       
   224     }
       
   225 
       
   226     /* Construct the SECItem representation of point Q */
       
   227     pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
       
   228     CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
       
   229                                       (mp_size) len) );
       
   230     CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
       
   231                                       (mp_size) len) );
       
   232 
       
   233     rv = SECSuccess;
       
   234 
       
   235 #if EC_DEBUG
       
   236     printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
       
   237     for (i = 0; i < pointQ->len; i++)
       
   238             printf("%02x:", pointQ->data[i]);
       
   239     printf("\n");
       
   240 #endif
       
   241 
       
   242 cleanup:
       
   243     ECGroup_free(group);
       
   244     mp_clear(&Px);
       
   245     mp_clear(&Py);
       
   246     mp_clear(&Qx);
       
   247     mp_clear(&Qy);
       
   248     mp_clear(&Gx);
       
   249     mp_clear(&Gy);
       
   250     mp_clear(&order);
       
   251     mp_clear(&irreducible);
       
   252     mp_clear(&a);
       
   253     mp_clear(&b);
       
   254     if (err) {
       
   255         MP_TO_SEC_ERROR(err);
       
   256         rv = SECFailure;
       
   257     }
       
   258 
       
   259     return rv;
       
   260 }
       
   261 
       
   262 /* Generates a new EC key pair. The private key is a supplied
       
   263  * value and the public key is the result of performing a scalar
       
   264  * point multiplication of that value with the curve's base point.
       
   265  */
       
   266 SECStatus
       
   267 ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
       
   268     const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
       
   269 {
       
   270     SECStatus rv = SECFailure;
       
   271     PRArenaPool *arena;
       
   272     ECPrivateKey *key;
       
   273     mp_int k;
       
   274     mp_err err = MP_OKAY;
       
   275     int len;
       
   276 
       
   277 #if EC_DEBUG
       
   278     printf("ec_NewKey called\n");
       
   279 #endif
       
   280 
       
   281 #ifndef _WIN32
       
   282 int printf();
       
   283 #endif /* _WIN32 */
       
   284 
       
   285     if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
       
   286         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   287         return SECFailure;
       
   288     }
       
   289 
       
   290     /* Initialize an arena for the EC key. */
       
   291     if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
       
   292         return SECFailure;
       
   293 
       
   294     key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
       
   295         kmflag);
       
   296     if (!key) {
       
   297         PORT_FreeArena(arena, PR_TRUE);
       
   298         return SECFailure;
       
   299     }
       
   300 
       
   301     /* Set the version number (SEC 1 section C.4 says it should be 1) */
       
   302     SECITEM_AllocItem(arena, &key->version, 1, kmflag);
       
   303     key->version.data[0] = 1;
       
   304 
       
   305     /* Copy all of the fields from the ECParams argument to the
       
   306      * ECParams structure within the private key.
       
   307      */
       
   308     key->ecParams.arena = arena;
       
   309     key->ecParams.type = ecParams->type;
       
   310     key->ecParams.fieldID.size = ecParams->fieldID.size;
       
   311     key->ecParams.fieldID.type = ecParams->fieldID.type;
       
   312     if (ecParams->fieldID.type == ec_field_GFp) {
       
   313         CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
       
   314             &ecParams->fieldID.u.prime, kmflag));
       
   315     } else {
       
   316         CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
       
   317             &ecParams->fieldID.u.poly, kmflag));
       
   318     }
       
   319     key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
       
   320     key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
       
   321     key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
       
   322     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
       
   323         &ecParams->curve.a, kmflag));
       
   324     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
       
   325         &ecParams->curve.b, kmflag));
       
   326     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
       
   327         &ecParams->curve.seed, kmflag));
       
   328     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
       
   329         &ecParams->base, kmflag));
       
   330     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
       
   331         &ecParams->order, kmflag));
       
   332     key->ecParams.cofactor = ecParams->cofactor;
       
   333     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
       
   334         &ecParams->DEREncoding, kmflag));
       
   335     key->ecParams.name = ecParams->name;
       
   336     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
       
   337         &ecParams->curveOID, kmflag));
       
   338 
       
   339     len = (ecParams->fieldID.size + 7) >> 3;
       
   340     SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
       
   341     len = ecParams->order.len;
       
   342     SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
       
   343 
       
   344     /* Copy private key */
       
   345     if (privKeyLen >= len) {
       
   346         memcpy(key->privateValue.data, privKeyBytes, len);
       
   347     } else {
       
   348         memset(key->privateValue.data, 0, (len - privKeyLen));
       
   349         memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
       
   350     }
       
   351 
       
   352     /* Compute corresponding public key */
       
   353     MP_DIGITS(&k) = 0;
       
   354     CHECK_MPI_OK( mp_init(&k, kmflag) );
       
   355     CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
       
   356         (mp_size) len) );
       
   357 
       
   358     rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
       
   359     if (rv != SECSuccess) goto cleanup;
       
   360     *privKey = key;
       
   361 
       
   362 cleanup:
       
   363     mp_clear(&k);
       
   364     if (rv)
       
   365         PORT_FreeArena(arena, PR_TRUE);
       
   366 
       
   367 #if EC_DEBUG
       
   368     printf("ec_NewKey returning %s\n",
       
   369         (rv == SECSuccess) ? "success" : "failure");
       
   370 #endif
       
   371 
       
   372     return rv;
       
   373 
       
   374 }
       
   375 
       
   376 /* Generates a new EC key pair. The private key is a supplied
       
   377  * random value (in seed) and the public key is the result of
       
   378  * performing a scalar point multiplication of that value with
       
   379  * the curve's base point.
       
   380  */
       
   381 SECStatus
       
   382 EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
       
   383     const unsigned char *seed, int seedlen, int kmflag)
       
   384 {
       
   385     SECStatus rv = SECFailure;
       
   386     rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
       
   387     return rv;
       
   388 }
       
   389 
       
   390 /* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
       
   391  * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
       
   392  * random number generator.
       
   393  *
       
   394  * Parameters
       
   395  * - order: a buffer that holds the curve's group order
       
   396  * - len: the length in octets of the order buffer
       
   397  * - random: a buffer of 2 * len random bytes
       
   398  * - randomlen: the length in octets of the random buffer
       
   399  *
       
   400  * Return Value
       
   401  * Returns a buffer of len octets that holds the private key. The caller
       
   402  * is responsible for freeing the buffer with PORT_ZFree.
       
   403  */
       
   404 static unsigned char *
       
   405 ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
       
   406     const unsigned char *random, int randomlen, int kmflag)
       
   407 {
       
   408     SECStatus rv = SECSuccess;
       
   409     mp_err err;
       
   410     unsigned char *privKeyBytes = NULL;
       
   411     mp_int privKeyVal, order_1, one;
       
   412 
       
   413     MP_DIGITS(&privKeyVal) = 0;
       
   414     MP_DIGITS(&order_1) = 0;
       
   415     MP_DIGITS(&one) = 0;
       
   416     CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
       
   417     CHECK_MPI_OK( mp_init(&order_1, kmflag) );
       
   418     CHECK_MPI_OK( mp_init(&one, kmflag) );
       
   419 
       
   420     /*
       
   421      * Reduces the 2*len buffer of random bytes modulo the group order.
       
   422      */
       
   423     if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
       
   424     if (randomlen != 2 * len) {
       
   425         goto cleanup;
       
   426     }
       
   427     /* No need to generate - random bytes are now supplied */
       
   428     /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
       
   429     memcpy(privKeyBytes, random, randomlen);
       
   430 
       
   431     CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
       
   432     CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
       
   433     CHECK_MPI_OK( mp_set_int(&one, 1) );
       
   434     CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
       
   435     CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
       
   436     CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
       
   437     CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
       
   438     memset(privKeyBytes+len, 0, len);
       
   439 cleanup:
       
   440     mp_clear(&privKeyVal);
       
   441     mp_clear(&order_1);
       
   442     mp_clear(&one);
       
   443     if (err < MP_OKAY) {
       
   444         MP_TO_SEC_ERROR(err);
       
   445         rv = SECFailure;
       
   446     }
       
   447     if (rv != SECSuccess && privKeyBytes) {
       
   448 #ifdef _KERNEL
       
   449         kmem_free(privKeyBytes, 2*len);
       
   450 #else
       
   451         free(privKeyBytes);
       
   452 #endif
       
   453         privKeyBytes = NULL;
       
   454     }
       
   455     return privKeyBytes;
       
   456 }
       
   457 
       
   458 /* Generates a new EC key pair. The private key is a random value and
       
   459  * the public key is the result of performing a scalar point multiplication
       
   460  * of that value with the curve's base point.
       
   461  */
       
   462 SECStatus
       
   463 EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
       
   464     const unsigned char* random, int randomlen, int kmflag)
       
   465 {
       
   466     SECStatus rv = SECFailure;
       
   467     int len;
       
   468     unsigned char *privKeyBytes = NULL;
       
   469 
       
   470     if (!ecParams) {
       
   471         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   472         return SECFailure;
       
   473     }
       
   474 
       
   475     len = ecParams->order.len;
       
   476     privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
       
   477         random, randomlen, kmflag);
       
   478     if (privKeyBytes == NULL) goto cleanup;
       
   479     /* generate public key */
       
   480     CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
       
   481 
       
   482 cleanup:
       
   483     if (privKeyBytes) {
       
   484         PORT_ZFree(privKeyBytes, len * 2);
       
   485     }
       
   486 #if EC_DEBUG
       
   487     printf("EC_NewKey returning %s\n",
       
   488         (rv == SECSuccess) ? "success" : "failure");
       
   489 #endif
       
   490 
       
   491     return rv;
       
   492 }
       
   493 
       
   494 /* Validates an EC public key as described in Section 5.2.2 of
       
   495  * X9.62. The ECDH primitive when used without the cofactor does
       
   496  * not address small subgroup attacks, which may occur when the
       
   497  * public key is not valid. These attacks can be prevented by
       
   498  * validating the public key before using ECDH.
       
   499  */
       
   500 SECStatus
       
   501 EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
       
   502 {
       
   503     mp_int Px, Py;
       
   504     ECGroup *group = NULL;
       
   505     SECStatus rv = SECFailure;
       
   506     mp_err err = MP_OKAY;
       
   507     int len;
       
   508 
       
   509     if (!ecParams || !publicValue) {
       
   510         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   511         return SECFailure;
       
   512     }
       
   513 
       
   514     /* NOTE: We only support uncompressed points for now */
       
   515     len = (ecParams->fieldID.size + 7) >> 3;
       
   516     if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
       
   517         PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
       
   518         return SECFailure;
       
   519     } else if (publicValue->len != (2 * len + 1)) {
       
   520         PORT_SetError(SEC_ERROR_BAD_KEY);
       
   521         return SECFailure;
       
   522     }
       
   523 
       
   524     MP_DIGITS(&Px) = 0;
       
   525     MP_DIGITS(&Py) = 0;
       
   526     CHECK_MPI_OK( mp_init(&Px, kmflag) );
       
   527     CHECK_MPI_OK( mp_init(&Py, kmflag) );
       
   528 
       
   529     /* Initialize Px and Py */
       
   530     CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
       
   531     CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
       
   532 
       
   533     /* construct from named params */
       
   534     group = ECGroup_fromName(ecParams->name, kmflag);
       
   535     if (group == NULL) {
       
   536         /*
       
   537          * ECGroup_fromName fails if ecParams->name is not a valid
       
   538          * ECCurveName value, or if we run out of memory, or perhaps
       
   539          * for other reasons.  Unfortunately if ecParams->name is a
       
   540          * valid ECCurveName value, we don't know what the right error
       
   541          * code should be because ECGroup_fromName doesn't return an
       
   542          * error code to the caller.  Set err to MP_UNDEF because
       
   543          * that's what ECGroup_fromName uses internally.
       
   544          */
       
   545         if ((ecParams->name <= ECCurve_noName) ||
       
   546             (ecParams->name >= ECCurve_pastLastCurve)) {
       
   547             err = MP_BADARG;
       
   548         } else {
       
   549             err = MP_UNDEF;
       
   550         }
       
   551         goto cleanup;
       
   552     }
       
   553 
       
   554     /* validate public point */
       
   555     if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
       
   556         if (err == MP_NO) {
       
   557             PORT_SetError(SEC_ERROR_BAD_KEY);
       
   558             rv = SECFailure;
       
   559             err = MP_OKAY;  /* don't change the error code */
       
   560         }
       
   561         goto cleanup;
       
   562     }
       
   563 
       
   564     rv = SECSuccess;
       
   565 
       
   566 cleanup:
       
   567     ECGroup_free(group);
       
   568     mp_clear(&Px);
       
   569     mp_clear(&Py);
       
   570     if (err) {
       
   571         MP_TO_SEC_ERROR(err);
       
   572         rv = SECFailure;
       
   573     }
       
   574     return rv;
       
   575 }
       
   576 
       
   577 /*
       
   578 ** Performs an ECDH key derivation by computing the scalar point
       
   579 ** multiplication of privateValue and publicValue (with or without the
       
   580 ** cofactor) and returns the x-coordinate of the resulting elliptic
       
   581 ** curve point in derived secret.  If successful, derivedSecret->data
       
   582 ** is set to the address of the newly allocated buffer containing the
       
   583 ** derived secret, and derivedSecret->len is the size of the secret
       
   584 ** produced. It is the caller's responsibility to free the allocated
       
   585 ** buffer containing the derived secret.
       
   586 */
       
   587 SECStatus
       
   588 ECDH_Derive(SECItem  *publicValue,
       
   589             ECParams *ecParams,
       
   590             SECItem  *privateValue,
       
   591             PRBool    withCofactor,
       
   592             SECItem  *derivedSecret,
       
   593             int kmflag)
       
   594 {
       
   595     SECStatus rv = SECFailure;
       
   596     unsigned int len = 0;
       
   597     SECItem pointQ = {siBuffer, NULL, 0};
       
   598     mp_int k; /* to hold the private value */
       
   599     mp_int cofactor;
       
   600     mp_err err = MP_OKAY;
       
   601 #if EC_DEBUG
       
   602     int i;
       
   603 #endif
       
   604 
       
   605     if (!publicValue || !ecParams || !privateValue ||
       
   606         !derivedSecret) {
       
   607         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   608         return SECFailure;
       
   609     }
       
   610 
       
   611     memset(derivedSecret, 0, sizeof *derivedSecret);
       
   612     len = (ecParams->fieldID.size + 7) >> 3;
       
   613     pointQ.len = 2*len + 1;
       
   614     if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
       
   615 
       
   616     MP_DIGITS(&k) = 0;
       
   617     CHECK_MPI_OK( mp_init(&k, kmflag) );
       
   618     CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
       
   619                                           (mp_size) privateValue->len) );
       
   620 
       
   621     if (withCofactor && (ecParams->cofactor != 1)) {
       
   622             /* multiply k with the cofactor */
       
   623             MP_DIGITS(&cofactor) = 0;
       
   624             CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
       
   625             mp_set(&cofactor, ecParams->cofactor);
       
   626             CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
       
   627     }
       
   628 
       
   629     /* Multiply our private key and peer's public point */
       
   630     if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
       
   631         ec_point_at_infinity(&pointQ))
       
   632         goto cleanup;
       
   633 
       
   634     /* Allocate memory for the derived secret and copy
       
   635      * the x co-ordinate of pointQ into it.
       
   636      */
       
   637     SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
       
   638     memcpy(derivedSecret->data, pointQ.data + 1, len);
       
   639 
       
   640     rv = SECSuccess;
       
   641 
       
   642 #if EC_DEBUG
       
   643     printf("derived_secret:\n");
       
   644     for (i = 0; i < derivedSecret->len; i++)
       
   645         printf("%02x:", derivedSecret->data[i]);
       
   646     printf("\n");
       
   647 #endif
       
   648 
       
   649 cleanup:
       
   650     mp_clear(&k);
       
   651 
       
   652     if (pointQ.data) {
       
   653         PORT_ZFree(pointQ.data, 2*len + 1);
       
   654     }
       
   655 
       
   656     return rv;
       
   657 }
       
   658 
       
   659 /* Computes the ECDSA signature (a concatenation of two values r and s)
       
   660  * on the digest using the given key and the random value kb (used in
       
   661  * computing s).
       
   662  */
       
   663 SECStatus
       
   664 ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
       
   665     const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
       
   666 {
       
   667     SECStatus rv = SECFailure;
       
   668     mp_int x1;
       
   669     mp_int d, k;     /* private key, random integer */
       
   670     mp_int r, s;     /* tuple (r, s) is the signature */
       
   671     mp_int n;
       
   672     mp_err err = MP_OKAY;
       
   673     ECParams *ecParams = NULL;
       
   674     SECItem kGpoint = { siBuffer, NULL, 0};
       
   675     int flen = 0;    /* length in bytes of the field size */
       
   676     unsigned olen;   /* length in bytes of the base point order */
       
   677 
       
   678 #if EC_DEBUG
       
   679     char mpstr[256];
       
   680 #endif
       
   681 
       
   682     /* Initialize MPI integers. */
       
   683     /* must happen before the first potential call to cleanup */
       
   684     MP_DIGITS(&x1) = 0;
       
   685     MP_DIGITS(&d) = 0;
       
   686     MP_DIGITS(&k) = 0;
       
   687     MP_DIGITS(&r) = 0;
       
   688     MP_DIGITS(&s) = 0;
       
   689     MP_DIGITS(&n) = 0;
       
   690 
       
   691     /* Check args */
       
   692     if (!key || !signature || !digest || !kb || (kblen < 0)) {
       
   693         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   694         goto cleanup;
       
   695     }
       
   696 
       
   697     ecParams = &(key->ecParams);
       
   698     flen = (ecParams->fieldID.size + 7) >> 3;
       
   699     olen = ecParams->order.len;
       
   700     if (signature->data == NULL) {
       
   701         /* a call to get the signature length only */
       
   702         goto finish;
       
   703     }
       
   704     if (signature->len < 2*olen) {
       
   705         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
       
   706         rv = SECBufferTooSmall;
       
   707         goto cleanup;
       
   708     }
       
   709 
       
   710 
       
   711     CHECK_MPI_OK( mp_init(&x1, kmflag) );
       
   712     CHECK_MPI_OK( mp_init(&d, kmflag) );
       
   713     CHECK_MPI_OK( mp_init(&k, kmflag) );
       
   714     CHECK_MPI_OK( mp_init(&r, kmflag) );
       
   715     CHECK_MPI_OK( mp_init(&s, kmflag) );
       
   716     CHECK_MPI_OK( mp_init(&n, kmflag) );
       
   717 
       
   718     SECITEM_TO_MPINT( ecParams->order, &n );
       
   719     SECITEM_TO_MPINT( key->privateValue, &d );
       
   720     CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
       
   721     /* Make sure k is in the interval [1, n-1] */
       
   722     if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
       
   723 #if EC_DEBUG
       
   724         printf("k is outside [1, n-1]\n");
       
   725         mp_tohex(&k, mpstr);
       
   726         printf("k : %s \n", mpstr);
       
   727         mp_tohex(&n, mpstr);
       
   728         printf("n : %s \n", mpstr);
       
   729 #endif
       
   730         PORT_SetError(SEC_ERROR_NEED_RANDOM);
       
   731         goto cleanup;
       
   732     }
       
   733 
       
   734     /*
       
   735     ** ANSI X9.62, Section 5.3.2, Step 2
       
   736     **
       
   737     ** Compute kG
       
   738     */
       
   739     kGpoint.len = 2*flen + 1;
       
   740     kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
       
   741     if ((kGpoint.data == NULL) ||
       
   742         (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
       
   743             != SECSuccess))
       
   744         goto cleanup;
       
   745 
       
   746     /*
       
   747     ** ANSI X9.62, Section 5.3.3, Step 1
       
   748     **
       
   749     ** Extract the x co-ordinate of kG into x1
       
   750     */
       
   751     CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
       
   752                                           (mp_size) flen) );
       
   753 
       
   754     /*
       
   755     ** ANSI X9.62, Section 5.3.3, Step 2
       
   756     **
       
   757     ** r = x1 mod n  NOTE: n is the order of the curve
       
   758     */
       
   759     CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
       
   760 
       
   761     /*
       
   762     ** ANSI X9.62, Section 5.3.3, Step 3
       
   763     **
       
   764     ** verify r != 0
       
   765     */
       
   766     if (mp_cmp_z(&r) == 0) {
       
   767         PORT_SetError(SEC_ERROR_NEED_RANDOM);
       
   768         goto cleanup;
       
   769     }
       
   770 
       
   771     /*
       
   772     ** ANSI X9.62, Section 5.3.3, Step 4
       
   773     **
       
   774     ** s = (k**-1 * (HASH(M) + d*r)) mod n
       
   775     */
       
   776     SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */
       
   777 
       
   778     /* In the definition of EC signing, digests are truncated
       
   779      * to the length of n in bits.
       
   780      * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
       
   781     if (digest->len*8 > ecParams->fieldID.size) {
       
   782         mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
       
   783     }
       
   784 
       
   785 #if EC_DEBUG
       
   786     mp_todecimal(&n, mpstr);
       
   787     printf("n : %s (dec)\n", mpstr);
       
   788     mp_todecimal(&d, mpstr);
       
   789     printf("d : %s (dec)\n", mpstr);
       
   790     mp_tohex(&x1, mpstr);
       
   791     printf("x1: %s\n", mpstr);
       
   792     mp_todecimal(&s, mpstr);
       
   793     printf("digest: %s (decimal)\n", mpstr);
       
   794     mp_todecimal(&r, mpstr);
       
   795     printf("r : %s (dec)\n", mpstr);
       
   796     mp_tohex(&r, mpstr);
       
   797     printf("r : %s\n", mpstr);
       
   798 #endif
       
   799 
       
   800     CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
       
   801     CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
       
   802     CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
       
   803     CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */
       
   804 
       
   805 #if EC_DEBUG
       
   806     mp_todecimal(&s, mpstr);
       
   807     printf("s : %s (dec)\n", mpstr);
       
   808     mp_tohex(&s, mpstr);
       
   809     printf("s : %s\n", mpstr);
       
   810 #endif
       
   811 
       
   812     /*
       
   813     ** ANSI X9.62, Section 5.3.3, Step 5
       
   814     **
       
   815     ** verify s != 0
       
   816     */
       
   817     if (mp_cmp_z(&s) == 0) {
       
   818         PORT_SetError(SEC_ERROR_NEED_RANDOM);
       
   819         goto cleanup;
       
   820     }
       
   821 
       
   822    /*
       
   823     **
       
   824     ** Signature is tuple (r, s)
       
   825     */
       
   826     CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
       
   827     CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
       
   828 finish:
       
   829     signature->len = 2*olen;
       
   830 
       
   831     rv = SECSuccess;
       
   832     err = MP_OKAY;
       
   833 cleanup:
       
   834     mp_clear(&x1);
       
   835     mp_clear(&d);
       
   836     mp_clear(&k);
       
   837     mp_clear(&r);
       
   838     mp_clear(&s);
       
   839     mp_clear(&n);
       
   840 
       
   841     if (kGpoint.data) {
       
   842         PORT_ZFree(kGpoint.data, 2*flen + 1);
       
   843     }
       
   844 
       
   845     if (err) {
       
   846         MP_TO_SEC_ERROR(err);
       
   847         rv = SECFailure;
       
   848     }
       
   849 
       
   850 #if EC_DEBUG
       
   851     printf("ECDSA signing with seed %s\n",
       
   852         (rv == SECSuccess) ? "succeeded" : "failed");
       
   853 #endif
       
   854 
       
   855    return rv;
       
   856 }
       
   857 
       
   858 /*
       
   859 ** Computes the ECDSA signature on the digest using the given key
       
   860 ** and a random seed.
       
   861 */
       
   862 SECStatus
       
   863 ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
       
   864     const unsigned char* random, int randomLen, int kmflag)
       
   865 {
       
   866     SECStatus rv = SECFailure;
       
   867     int len;
       
   868     unsigned char *kBytes= NULL;
       
   869 
       
   870     if (!key) {
       
   871         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   872         return SECFailure;
       
   873     }
       
   874 
       
   875     /* Generate random value k */
       
   876     len = key->ecParams.order.len;
       
   877     kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
       
   878         random, randomLen, kmflag);
       
   879     if (kBytes == NULL) goto cleanup;
       
   880 
       
   881     /* Generate ECDSA signature with the specified k value */
       
   882     rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
       
   883 
       
   884 cleanup:
       
   885     if (kBytes) {
       
   886         PORT_ZFree(kBytes, len * 2);
       
   887     }
       
   888 
       
   889 #if EC_DEBUG
       
   890     printf("ECDSA signing %s\n",
       
   891         (rv == SECSuccess) ? "succeeded" : "failed");
       
   892 #endif
       
   893 
       
   894     return rv;
       
   895 }
       
   896 
       
   897 /*
       
   898 ** Checks the signature on the given digest using the key provided.
       
   899 */
       
   900 SECStatus
       
   901 ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
       
   902                  const SECItem *digest, int kmflag)
       
   903 {
       
   904     SECStatus rv = SECFailure;
       
   905     mp_int r_, s_;           /* tuple (r', s') is received signature) */
       
   906     mp_int c, u1, u2, v;     /* intermediate values used in verification */
       
   907     mp_int x1;
       
   908     mp_int n;
       
   909     mp_err err = MP_OKAY;
       
   910     ECParams *ecParams = NULL;
       
   911     SECItem pointC = { siBuffer, NULL, 0 };
       
   912     int slen;       /* length in bytes of a half signature (r or s) */
       
   913     int flen;       /* length in bytes of the field size */
       
   914     unsigned olen;  /* length in bytes of the base point order */
       
   915 
       
   916 #if EC_DEBUG
       
   917     char mpstr[256];
       
   918     printf("ECDSA verification called\n");
       
   919 #endif
       
   920 
       
   921     /* Initialize MPI integers. */
       
   922     /* must happen before the first potential call to cleanup */
       
   923     MP_DIGITS(&r_) = 0;
       
   924     MP_DIGITS(&s_) = 0;
       
   925     MP_DIGITS(&c) = 0;
       
   926     MP_DIGITS(&u1) = 0;
       
   927     MP_DIGITS(&u2) = 0;
       
   928     MP_DIGITS(&x1) = 0;
       
   929     MP_DIGITS(&v)  = 0;
       
   930     MP_DIGITS(&n)  = 0;
       
   931 
       
   932     /* Check args */
       
   933     if (!key || !signature || !digest) {
       
   934         PORT_SetError(SEC_ERROR_INVALID_ARGS);
       
   935         goto cleanup;
       
   936     }
       
   937 
       
   938     ecParams = &(key->ecParams);
       
   939     flen = (ecParams->fieldID.size + 7) >> 3;
       
   940     olen = ecParams->order.len;
       
   941     if (signature->len == 0 || signature->len%2 != 0 ||
       
   942         signature->len > 2*olen) {
       
   943         PORT_SetError(SEC_ERROR_INPUT_LEN);
       
   944         goto cleanup;
       
   945     }
       
   946     slen = signature->len/2;
       
   947 
       
   948     SECITEM_AllocItem(NULL, &pointC, 2*flen + 1, kmflag);
       
   949     if (pointC.data == NULL)
       
   950         goto cleanup;
       
   951 
       
   952     CHECK_MPI_OK( mp_init(&r_, kmflag) );
       
   953     CHECK_MPI_OK( mp_init(&s_, kmflag) );
       
   954     CHECK_MPI_OK( mp_init(&c, kmflag)  );
       
   955     CHECK_MPI_OK( mp_init(&u1, kmflag) );
       
   956     CHECK_MPI_OK( mp_init(&u2, kmflag) );
       
   957     CHECK_MPI_OK( mp_init(&x1, kmflag)  );
       
   958     CHECK_MPI_OK( mp_init(&v, kmflag)  );
       
   959     CHECK_MPI_OK( mp_init(&n, kmflag)  );
       
   960 
       
   961     /*
       
   962     ** Convert received signature (r', s') into MPI integers.
       
   963     */
       
   964     CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
       
   965     CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
       
   966 
       
   967     /*
       
   968     ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
       
   969     **
       
   970     ** Verify that 0 < r' < n and 0 < s' < n
       
   971     */
       
   972     SECITEM_TO_MPINT(ecParams->order, &n);
       
   973     if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
       
   974         mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
       
   975         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
       
   976         goto cleanup; /* will return rv == SECFailure */
       
   977     }
       
   978 
       
   979     /*
       
   980     ** ANSI X9.62, Section 5.4.2, Step 3
       
   981     **
       
   982     ** c = (s')**-1 mod n
       
   983     */
       
   984     CHECK_MPI_OK( mp_invmod(&s_, &n, &c) );      /* c = (s')**-1 mod n */
       
   985 
       
   986     /*
       
   987     ** ANSI X9.62, Section 5.4.2, Step 4
       
   988     **
       
   989     ** u1 = ((HASH(M')) * c) mod n
       
   990     */
       
   991     SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */
       
   992 
       
   993     /* In the definition of EC signing, digests are truncated
       
   994      * to the length of n in bits.
       
   995      * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
       
   996     if (digest->len*8 > ecParams->fieldID.size) {  /* u1 = HASH(M')     */
       
   997         mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
       
   998     }
       
   999 
       
  1000 #if EC_DEBUG
       
  1001     mp_todecimal(&r_, mpstr);
       
  1002     printf("r_: %s (dec)\n", mpstr);
       
  1003     mp_todecimal(&s_, mpstr);
       
  1004     printf("s_: %s (dec)\n", mpstr);
       
  1005     mp_todecimal(&c, mpstr);
       
  1006     printf("c : %s (dec)\n", mpstr);
       
  1007     mp_todecimal(&u1, mpstr);
       
  1008     printf("digest: %s (dec)\n", mpstr);
       
  1009 #endif
       
  1010 
       
  1011     CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) );  /* u1 = u1 * c mod n */
       
  1012 
       
  1013     /*
       
  1014     ** ANSI X9.62, Section 5.4.2, Step 4
       
  1015     **
       
  1016     ** u2 = ((r') * c) mod n
       
  1017     */
       
  1018     CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
       
  1019 
       
  1020     /*
       
  1021     ** ANSI X9.62, Section 5.4.3, Step 1
       
  1022     **
       
  1023     ** Compute u1*G + u2*Q
       
  1024     ** Here, A = u1.G     B = u2.Q    and   C = A + B
       
  1025     ** If the result, C, is the point at infinity, reject the signature
       
  1026     */
       
  1027     if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag)
       
  1028         != SECSuccess) {
       
  1029         rv = SECFailure;
       
  1030         goto cleanup;
       
  1031     }
       
  1032     if (ec_point_at_infinity(&pointC)) {
       
  1033         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
       
  1034         rv = SECFailure;
       
  1035         goto cleanup;
       
  1036     }
       
  1037 
       
  1038     CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );
       
  1039 
       
  1040     /*
       
  1041     ** ANSI X9.62, Section 5.4.4, Step 2
       
  1042     **
       
  1043     ** v = x1 mod n
       
  1044     */
       
  1045     CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
       
  1046 
       
  1047 #if EC_DEBUG
       
  1048     mp_todecimal(&r_, mpstr);
       
  1049     printf("r_: %s (dec)\n", mpstr);
       
  1050     mp_todecimal(&v, mpstr);
       
  1051     printf("v : %s (dec)\n", mpstr);
       
  1052 #endif
       
  1053 
       
  1054     /*
       
  1055     ** ANSI X9.62, Section 5.4.4, Step 3
       
  1056     **
       
  1057     ** Verification:  v == r'
       
  1058     */
       
  1059     if (mp_cmp(&v, &r_)) {
       
  1060         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
       
  1061         rv = SECFailure; /* Signature failed to verify. */
       
  1062     } else {
       
  1063         rv = SECSuccess; /* Signature verified. */
       
  1064     }
       
  1065 
       
  1066 #if EC_DEBUG
       
  1067     mp_todecimal(&u1, mpstr);
       
  1068     printf("u1: %s (dec)\n", mpstr);
       
  1069     mp_todecimal(&u2, mpstr);
       
  1070     printf("u2: %s (dec)\n", mpstr);
       
  1071     mp_tohex(&x1, mpstr);
       
  1072     printf("x1: %s\n", mpstr);
       
  1073     mp_todecimal(&v, mpstr);
       
  1074     printf("v : %s (dec)\n", mpstr);
       
  1075 #endif
       
  1076 
       
  1077 cleanup:
       
  1078     mp_clear(&r_);
       
  1079     mp_clear(&s_);
       
  1080     mp_clear(&c);
       
  1081     mp_clear(&u1);
       
  1082     mp_clear(&u2);
       
  1083     mp_clear(&x1);
       
  1084     mp_clear(&v);
       
  1085     mp_clear(&n);
       
  1086 
       
  1087     if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
       
  1088     if (err) {
       
  1089         MP_TO_SEC_ERROR(err);
       
  1090         rv = SECFailure;
       
  1091     }
       
  1092 
       
  1093 #if EC_DEBUG
       
  1094     printf("ECDSA verification %s\n",
       
  1095         (rv == SECSuccess) ? "succeeded" : "failed");
       
  1096 #endif
       
  1097 
       
  1098     return rv;
       
  1099 }