/*
* Use is subject to license terms.
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* *********************************************************************
*
* The Original Code is the Elliptic Curve Cryptography library.
*
* The Initial Developer of the Original Code is
* Sun Microsystems, Inc.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
*
*********************************************************************** */
#include "mplogic.h"
#include "ec.h"
#include "ecl.h"
#ifndef _KERNEL
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <stdio.h>
#include <strings.h>
#endif /* _WIN32 */
#endif
#include "ecl-exp.h"
#include "mpi.h"
#include "ecc_impl.h"
#ifdef _KERNEL
#else
#ifndef _WIN32
#else
#endif /* _WIN32 */
#endif
/*
* Returns true if pointP is the point at infinity, false otherwise
*/
{
unsigned int i;
}
return PR_TRUE;
}
/*
* Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
* the curve whose parameters are encoded in params with base point G.
*/
{
#if 0 /* currently don't support non-named curves */
unsigned int irr_arr[5];
#endif
unsigned int len;
#if EC_DEBUG
int i;
printf("\n");
}
}
printf("\n");
}
#endif
/* NOTE: We only support uncompressed points for now */
return SECFailure;
};
}
MP_DIGITS(&irreducible) = 0;
MP_DIGITS(&a) = 0;
MP_DIGITS(&b) = 0;
/* Initialize Px and Py */
}
/* construct from named params, if possible */
}
#if 0 /* currently don't support non-named curves */
/* Set up mp_ints containing the curve coefficients */
} else {
irr_arr[4] = 0;
}
}
#endif
goto cleanup;
} else {
}
/* Construct the SECItem representation of point Q */
rv = SECSuccess;
#if EC_DEBUG
printf("\n");
#endif
mp_clear(&a);
mp_clear(&b);
if (err) {
rv = SECFailure;
}
return rv;
}
/* Generates a new EC key pair. The private key is a supplied
* value and the public key is the result of performing a scalar
* point multiplication of that value with the curve's base point.
*/
{
mp_int k;
int len;
#if EC_DEBUG
printf("ec_NewKey called\n");
#endif
return SECFailure;
}
/* Initialize an arena for the EC key. */
return SECFailure;
kmflag);
if (!key) {
return SECFailure;
}
/* Set the version number (SEC 1 section C.4 says it should be 1) */
/* Copy all of the fields from the ECParams argument to the
* ECParams structure within the private key.
*/
} else {
}
/* Copy private key */
if (privKeyLen >= len) {
} else {
}
/* Compute corresponding public key */
MP_DIGITS(&k) = 0;
mp_clear(&k);
if (rv) {
}
#if EC_DEBUG
printf("ec_NewKey returning %s\n",
#endif
return rv;
}
/* Generates a new EC key pair. The private key is a supplied
* random value (in seed) and the public key is the result of
* performing a scalar point multiplication of that value with
* the curve's base point.
*/
{
return rv;
}
/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
* modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
* random number generator.
*
* Parameters
* - order: a buffer that holds the curve's group order
* - len: the length in octets of the order buffer
* - random: a buffer of 2 * len random bytes
* - randomlen: the length in octets of the random buffer
*
* Return Value
* Returns a buffer of len octets that holds the private key. The caller
* is responsible for freeing the buffer with PORT_ZFree.
*/
static unsigned char *
{
MP_DIGITS(&privKeyVal) = 0;
/*
* Reduces the 2*len buffer of random bytes modulo the group order.
*/
}
/* No need to generate - random bytes are now supplied */
/* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
rv = SECFailure;
}
#ifdef _KERNEL
#else
#endif
privKeyBytes = NULL;
}
return privKeyBytes;
}
/* Generates a new EC key pair. The private key is a random value and
* the public key is the result of performing a scalar point multiplication
* of that value with the curve's base point.
*/
{
int len;
if (!ecParams) {
return SECFailure;
}
/* generate public key */
if (privKeyBytes) {
}
#if EC_DEBUG
printf("EC_NewKey returning %s\n",
#endif
return rv;
}
/* Validates an EC public key as described in Section 5.2.2 of
* X9.62. The ECDH primitive when used without the cofactor does
* not address small subgroup attacks, which may occur when the
* public key is not valid. These attacks can be prevented by
* validating the public key before using ECDH.
*/
{
unsigned int len;
if (!ecParams || !publicValue) {
return SECFailure;
}
/* NOTE: We only support uncompressed points for now */
return SECFailure;
return SECFailure;
}
/* Initialize Px and Py */
/* construct from named params */
/*
* ECGroup_fromName fails if ecParams->name is not a valid
* ECCurveName value, or if we run out of memory, or perhaps
* for other reasons. Unfortunately if ecParams->name is a
* valid ECCurveName value, we don't know what the right error
* code should be because ECGroup_fromName doesn't return an
* error code to the caller. Set err to MP_UNDEF because
* that's what ECGroup_fromName uses internally.
*/
} else {
}
goto cleanup;
}
/* validate public point */
rv = SECFailure;
}
goto cleanup;
}
rv = SECSuccess;
if (err) {
rv = SECFailure;
}
return rv;
}
/*
** Performs an ECDH key derivation by computing the scalar point
** multiplication of privateValue and publicValue (with or without the
** cofactor) and returns the x-coordinate of the resulting elliptic
** curve point in derived secret. If successful, derivedSecret->data
** is set to the address of the newly allocated buffer containing the
** derived secret, and derivedSecret->len is the size of the secret
** produced. It is the caller's responsibility to free the allocated
** buffer containing the derived secret.
*/
int kmflag)
{
unsigned int len = 0;
mp_int k; /* to hold the private value */
#if EC_DEBUG
int i;
#endif
!derivedSecret) {
return SECFailure;
}
MP_DIGITS(&k) = 0;
/* multiply k with the cofactor */
}
/* Multiply our private key and peer's public point */
goto cleanup;
/* Allocate memory for the derived secret and copy
* the x co-ordinate of pointQ into it.
*/
rv = SECSuccess;
#if EC_DEBUG
printf("derived_secret:\n");
for (i = 0; i < derivedSecret->len; i++)
printf("\n");
#endif
mp_clear(&k);
}
return rv;
}
/* Computes the ECDSA signature (a concatenation of two values r and s)
* on the digest using the given key and the random value kb (used in
* computing s).
*/
{
mp_int d, k; /* private key, random integer */
mp_int r, s; /* tuple (r, s) is the signature */
mp_int n;
#if EC_DEBUG
#endif
/* Initialize MPI integers. */
/* must happen before the first potential call to cleanup */
MP_DIGITS(&d) = 0;
MP_DIGITS(&k) = 0;
MP_DIGITS(&r) = 0;
MP_DIGITS(&s) = 0;
MP_DIGITS(&n) = 0;
/* Check args */
goto cleanup;
}
/* a call to get the signature length only */
goto finish;
}
goto cleanup;
}
/* Make sure k is in the interval [1, n-1] */
#if EC_DEBUG
printf("k is outside [1, n-1]\n");
#endif
goto cleanup;
}
/*
** ANSI X9.62, Section 5.3.2, Step 2
**
** Compute kG
*/
!= SECSuccess))
goto cleanup;
/*
** ANSI X9.62, Section 5.3.3, Step 1
**
** Extract the x co-ordinate of kG into x1
*/
/*
** ANSI X9.62, Section 5.3.3, Step 2
**
** r = x1 mod n NOTE: n is the order of the curve
*/
/*
** ANSI X9.62, Section 5.3.3, Step 3
**
** verify r != 0
*/
if (mp_cmp_z(&r) == 0) {
goto cleanup;
}
/*
** ANSI X9.62, Section 5.3.3, Step 4
**
** s = (k**-1 * (HASH(M) + d*r)) mod n
*/
/* In the definition of EC signing, digests are truncated
* to the length of n in bits.
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
}
#if EC_DEBUG
mp_todecimal(&n, mpstr);
mp_todecimal(&d, mpstr);
mp_todecimal(&s, mpstr);
mp_todecimal(&r, mpstr);
#endif
#if EC_DEBUG
mp_todecimal(&s, mpstr);
#endif
/*
** ANSI X9.62, Section 5.3.3, Step 5
**
** verify s != 0
*/
if (mp_cmp_z(&s) == 0) {
goto cleanup;
}
/*
**
** Signature is tuple (r, s)
*/
rv = SECSuccess;
mp_clear(&d);
mp_clear(&k);
mp_clear(&r);
mp_clear(&s);
mp_clear(&n);
}
if (err) {
rv = SECFailure;
}
#if EC_DEBUG
printf("ECDSA signing with seed %s\n",
#endif
return rv;
}
/*
** Computes the ECDSA signature on the digest using the given key
** and a random seed.
*/
{
int len;
if (!key) {
return SECFailure;
}
/* Generate random value k */
/* Generate ECDSA signature with the specified k value */
if (kBytes) {
}
#if EC_DEBUG
printf("ECDSA signing %s\n",
#endif
return rv;
}
/*
** Checks the signature on the given digest using the key provided.
*/
{
mp_int n;
#if EC_DEBUG
printf("ECDSA verification called\n");
#endif
/* Initialize MPI integers. */
/* must happen before the first potential call to cleanup */
MP_DIGITS(&c) = 0;
MP_DIGITS(&v) = 0;
MP_DIGITS(&n) = 0;
/* Check args */
goto cleanup;
}
goto cleanup;
}
goto cleanup;
/*
** Convert received signature (r', s') into MPI integers.
*/
/*
** ANSI X9.62, Section 5.4.2, Steps 1 and 2
**
** Verify that 0 < r' < n and 0 < s' < n
*/
goto cleanup; /* will return rv == SECFailure */
}
/*
** ANSI X9.62, Section 5.4.2, Step 3
**
** c = (s')**-1 mod n
*/
/*
** ANSI X9.62, Section 5.4.2, Step 4
**
** u1 = ((HASH(M')) * c) mod n
*/
/* In the definition of EC signing, digests are truncated
* to the length of n in bits.
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
/* u1 = HASH(M') */
}
#if EC_DEBUG
mp_todecimal(&c, mpstr);
#endif
/*
** ANSI X9.62, Section 5.4.2, Step 4
**
** u2 = ((r') * c) mod n
*/
/*
** ANSI X9.62, Section 5.4.3, Step 1
**
** Compute u1*G + u2*Q
** Here, A = u1.G B = u2.Q and C = A + B
** If the result, C, is the point at infinity, reject the signature
*/
!= SECSuccess) {
rv = SECFailure;
goto cleanup;
}
if (ec_point_at_infinity(&pointC)) {
rv = SECFailure;
goto cleanup;
}
/*
** ANSI X9.62, Section 5.4.4, Step 2
**
** v = x1 mod n
*/
#if EC_DEBUG
mp_todecimal(&v, mpstr);
#endif
/*
** ANSI X9.62, Section 5.4.4, Step 3
**
** Verification: v == r'
*/
} else {
}
#if EC_DEBUG
mp_todecimal(&v, mpstr);
#endif
mp_clear(&c);
mp_clear(&v);
mp_clear(&n);
if (err) {
rv = SECFailure;
}
#if EC_DEBUG
printf("ECDSA verification %s\n",
#endif
return rv;
}