/*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* 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
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Sun elects to use this software under the MPL license.
*/
#include "mplogic.h"
#include "ec.h"
#include "ecl.h"
#ifndef _KERNEL
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#endif
#include "ecl-exp.h"
#include "mpi.h"
#include "ecc_impl.h"
#ifdef _KERNEL
#else
#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
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
int printf();
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
*
* 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;
/* Generates 2*len random bytes using the global random bit generator
* (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then
* reduces modulo the group order.
*/
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;
}
kmflag);
/* 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.
*/
{
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 kmflag)
{
int len;
if (!key) {
return SECFailure;
}
/* Generate random value k */
kmflag);
/* 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.*/
}
#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;
}
/*
* Copy all of the fields from srcParams into dstParams
*/
{
} else {
}
&srcParams->DEREncoding, 0));
return SECSuccess;
return SECFailure;
}