8235710: Remove the legacy elliptic curves
Reviewed-by: xuelei, erikj
This commit is contained in:
parent
8239b67d4f
commit
0b83fc0150
@ -242,7 +242,6 @@ HOTSPOT_SETUP_MISC
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
JDKOPT_DETECT_INTREE_EC
|
||||
JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER
|
||||
JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
|
||||
JDKOPT_EXCLUDE_TRANSLATIONS
|
||||
|
@ -228,23 +228,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
|
||||
])
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Enable or disable the elliptic curve crypto implementation
|
||||
#
|
||||
AC_DEFUN_ONCE([JDKOPT_DETECT_INTREE_EC],
|
||||
[
|
||||
AC_MSG_CHECKING([if elliptic curve crypto implementation is present])
|
||||
|
||||
if test -d "${TOPDIR}/src/jdk.crypto.ec/share/native/libsunec/impl"; then
|
||||
ENABLE_INTREE_EC=true
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
ENABLE_INTREE_EC=false
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_SUBST(ENABLE_INTREE_EC)
|
||||
])
|
||||
|
||||
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
|
||||
[
|
||||
|
@ -53,11 +53,6 @@ public class CurveDB {
|
||||
|
||||
private static Collection<? extends NamedCurve> specCollection;
|
||||
|
||||
// Used by SunECEntries
|
||||
public static Collection<? extends NamedCurve>getSupportedCurves() {
|
||||
return specCollection;
|
||||
}
|
||||
|
||||
// Return a NamedCurve for the specified OID/name or null if unknown.
|
||||
public static NamedCurve lookup(String name) {
|
||||
NamedCurve spec = oidMap.get(name);
|
||||
|
@ -495,16 +495,7 @@ sun.security.krb5.maxReferrals=5
|
||||
# in the jdk.[tls|certpath|jar].disabledAlgorithms properties. To include this
|
||||
# list in any of the disabledAlgorithms properties, add the property name as
|
||||
# an entry.
|
||||
jdk.disabled.namedCurves = secp112r1, secp112r2, secp128r1, secp128r2, \
|
||||
secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, \
|
||||
secp224r1, secp256k1, sect113r1, sect113r2, sect131r1, sect131r2, \
|
||||
sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, \
|
||||
sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, \
|
||||
sect571k1, sect571r1, X9.62 c2tnb191v1, X9.62 c2tnb191v2, \
|
||||
X9.62 c2tnb191v3, X9.62 c2tnb239v1, X9.62 c2tnb239v2, X9.62 c2tnb239v3, \
|
||||
X9.62 c2tnb359v1, X9.62 c2tnb431r1, X9.62 prime192v2, X9.62 prime192v3, \
|
||||
X9.62 prime239v1, X9.62 prime239v2, X9.62 prime239v3, brainpoolP256r1, \
|
||||
brainpoolP320r1, brainpoolP384r1, brainpoolP512r1
|
||||
#jdk.disabled.namedCurves=
|
||||
|
||||
#
|
||||
# Algorithm restrictions for certification path (CertPath) processing
|
||||
@ -642,8 +633,7 @@ jdk.disabled.namedCurves = secp112r1, secp112r2, secp128r1, secp128r2, \
|
||||
#
|
||||
#
|
||||
jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
|
||||
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \
|
||||
include jdk.disabled.namedCurves
|
||||
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
|
||||
|
||||
#
|
||||
# Legacy algorithms for certification path (CertPath) processing and
|
||||
@ -707,7 +697,7 @@ jdk.security.legacyAlgorithms=SHA1, \
|
||||
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
|
||||
#
|
||||
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
|
||||
DSA keySize < 1024, include jdk.disabled.namedCurves
|
||||
DSA keySize < 1024
|
||||
|
||||
#
|
||||
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
|
||||
@ -742,8 +732,7 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
|
||||
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \
|
||||
# rsa_pkcs1_sha1, secp224r1
|
||||
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
|
||||
EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
|
||||
include jdk.disabled.namedCurves
|
||||
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
|
||||
|
||||
#
|
||||
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
|
||||
|
@ -169,22 +169,12 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
}
|
||||
byte[] result;
|
||||
Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
|
||||
if (resultOpt.isPresent()) {
|
||||
result = resultOpt.get();
|
||||
} else {
|
||||
if (SunEC.isNativeDisabled()) {
|
||||
NamedCurve privNC = CurveDB.lookup(privateKey.getParams());
|
||||
NamedCurve pubNC = CurveDB.lookup(publicKey.getParams());
|
||||
throw new IllegalStateException(
|
||||
new InvalidAlgorithmParameterException("Legacy SunEC " +
|
||||
"curve disabled, one or both keys: " +
|
||||
"Private: " + ((privNC != null) ?
|
||||
privNC.toString() : " unknown") +
|
||||
", PublicKey:" + ((pubNC != null) ?
|
||||
pubNC.toString() : " unknown")));
|
||||
}
|
||||
result = deriveKeyNative(privateKey, publicKey);
|
||||
if (resultOpt.isEmpty()) {
|
||||
throw new IllegalStateException(
|
||||
new InvalidAlgorithmParameterException("Curve not supported: " +
|
||||
publicKey.getParams().toString()));
|
||||
}
|
||||
result = resultOpt.get();
|
||||
publicKey = null;
|
||||
return result;
|
||||
}
|
||||
@ -263,42 +253,4 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
|
||||
return Optional.of(result);
|
||||
}
|
||||
|
||||
private static
|
||||
byte[] deriveKeyNative(ECPrivateKey privateKey, ECPublicKey publicKey) {
|
||||
|
||||
ECParameterSpec params = privateKey.getParams();
|
||||
byte[] s = privateKey.getS().toByteArray();
|
||||
byte[] encodedParams = // DER OID
|
||||
ECUtil.encodeECParameterSpec(null, params);
|
||||
|
||||
byte[] publicValue;
|
||||
if (publicKey instanceof ECPublicKeyImpl) {
|
||||
ECPublicKeyImpl ecPub = (ECPublicKeyImpl) publicKey;
|
||||
publicValue = ecPub.getEncodedPublicValue();
|
||||
} else { // instanceof ECPublicKey
|
||||
publicValue =
|
||||
ECUtil.encodePoint(publicKey.getW(), params.getCurve());
|
||||
}
|
||||
|
||||
try {
|
||||
return deriveKey(s, publicValue, encodedParams);
|
||||
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new ProviderException("Could not derive key", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a secret key using the public and private keys.
|
||||
*
|
||||
* @param s the private key's S value.
|
||||
* @param w the public key's W point (in uncompressed form).
|
||||
* @param encodedParams the curve's DER encoded object identifier.
|
||||
*
|
||||
* @return byte[] the secret key.
|
||||
*/
|
||||
private static native byte[] deriveKey(byte[] s, byte[] w,
|
||||
byte[] encodedParams) throws GeneralSecurityException;
|
||||
}
|
||||
|
@ -466,53 +466,6 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
}
|
||||
|
||||
|
||||
private Optional<byte[]> signDigestAvailable(ECPrivateKey privateKey,
|
||||
byte[] digest, SecureRandom random) throws SignatureException {
|
||||
|
||||
ECParameterSpec params = privateKey.getParams();
|
||||
|
||||
// seed is the key size + 64 bits
|
||||
int seedBits = params.getOrder().bitLength() + 64;
|
||||
Optional<ECDSAOperations> opsOpt =
|
||||
ECDSAOperations.forParameters(params);
|
||||
if (opsOpt.isEmpty()) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest,
|
||||
privateKey, random);
|
||||
return Optional.of(sig);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest,
|
||||
SecureRandom random) throws SignatureException {
|
||||
|
||||
byte[] s = privateKey.getS().toByteArray();
|
||||
ECParameterSpec params = privateKey.getParams();
|
||||
|
||||
// DER OID
|
||||
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
|
||||
int orderLength = params.getOrder().bitLength();
|
||||
|
||||
// seed is twice the order length (in bytes) plus 1
|
||||
byte[] seed = new byte[(((orderLength + 7) >> 3) + 1) * 2];
|
||||
|
||||
random.nextBytes(seed);
|
||||
|
||||
// random bits needed for timing countermeasures
|
||||
int timingArgument = random.nextInt();
|
||||
// values must be non-zero to enable countermeasures
|
||||
timingArgument |= 1;
|
||||
|
||||
try {
|
||||
return signDigest(digest, s, encodedParams, seed,
|
||||
timingArgument);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new SignatureException("Could not sign data", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// sign the data and return the signature. See JCA doc
|
||||
@Override
|
||||
protected byte[] engineSign() throws SignatureException {
|
||||
@ -522,21 +475,18 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
}
|
||||
|
||||
byte[] digest = getDigestValue();
|
||||
Optional<byte[]> sigOpt = signDigestAvailable(privateKey, digest, random);
|
||||
byte[] sig;
|
||||
if (sigOpt.isPresent()) {
|
||||
sig = sigOpt.get();
|
||||
} else {
|
||||
if (SunEC.isNativeDisabled()) {
|
||||
NamedCurve nc = CurveDB.lookup(privateKey.getParams());
|
||||
throw new SignatureException(
|
||||
new InvalidAlgorithmParameterException(
|
||||
"Legacy SunEC curve disabled: " +
|
||||
(nc != null ? nc.toString()
|
||||
: "unknown")));
|
||||
}
|
||||
sig = signDigestNative(privateKey, digest, random);
|
||||
ECParameterSpec params = privateKey.getParams();
|
||||
|
||||
// seed is the key size + 64 bits
|
||||
int seedBits = params.getOrder().bitLength() + 64;
|
||||
Optional<ECDSAOperations> opsOpt =
|
||||
ECDSAOperations.forParameters(params);
|
||||
if (opsOpt.isEmpty()) {
|
||||
throw new SignatureException("Curve not supported: " +
|
||||
params.toString());
|
||||
}
|
||||
byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest, privateKey,
|
||||
random);
|
||||
|
||||
if (p1363Format) {
|
||||
return sig;
|
||||
@ -557,59 +507,14 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
}
|
||||
|
||||
byte[] digest = getDigestValue();
|
||||
Optional<Boolean> verifyOpt
|
||||
= verifySignedDigestAvailable(publicKey, sig, digest);
|
||||
|
||||
if (verifyOpt.isPresent()) {
|
||||
return verifyOpt.get();
|
||||
} else {
|
||||
if (SunEC.isNativeDisabled()) {
|
||||
NamedCurve nc = CurveDB.lookup(publicKey.getParams());
|
||||
throw new SignatureException(
|
||||
new InvalidAlgorithmParameterException(
|
||||
"Legacy SunEC curve disabled: " +
|
||||
(nc != null ? nc.toString()
|
||||
: "unknown")));
|
||||
}
|
||||
|
||||
byte[] w;
|
||||
ECParameterSpec params = publicKey.getParams();
|
||||
// DER OID
|
||||
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
|
||||
|
||||
if (publicKey instanceof ECPublicKeyImpl) {
|
||||
w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
|
||||
} else { // instanceof ECPublicKey
|
||||
w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
|
||||
}
|
||||
|
||||
try {
|
||||
return verifySignedDigest(sig, digest, w, encodedParams);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new SignatureException("Could not verify signature", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Boolean> verifySignedDigestAvailable(
|
||||
ECPublicKey publicKey, byte[] sig, byte[] digestValue) {
|
||||
|
||||
ECParameterSpec params = publicKey.getParams();
|
||||
|
||||
Optional<ECDSAOperations> opsOpt =
|
||||
ECDSAOperations.forParameters(params);
|
||||
ECDSAOperations.forParameters(publicKey.getParams());
|
||||
if (opsOpt.isEmpty()) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
boolean result = verifySignedDigestImpl(opsOpt.get(), digestValue,
|
||||
publicKey, sig);
|
||||
return Optional.of(result);
|
||||
throw new SignatureException("Curve not supported: " +
|
||||
publicKey.getParams().toString());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verifySignedDigestImpl(ECDSAOperations ops,
|
||||
byte[] digest, ECPublicKey pub, byte[] sig) {
|
||||
return ops.verifySignedDigest(digest, sig, pub.getW());
|
||||
return opsOpt.get().verifySignedDigest(digest, sig, publicKey.getW());
|
||||
}
|
||||
|
||||
// set parameter, not supported. See JCA doc
|
||||
@ -657,40 +562,4 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
throw new ProviderException("Error retrieving EC parameters", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs the digest using the private key.
|
||||
*
|
||||
* @param digest the digest to be signed.
|
||||
* @param s the private key's S value.
|
||||
* @param encodedParams the curve's DER encoded object identifier.
|
||||
* @param seed the random seed.
|
||||
* @param timing When non-zero, the implmentation will use timing
|
||||
* countermeasures to hide secrets from timing channels. The EC
|
||||
* implementation will disable the countermeasures when this value is
|
||||
* zero, because the underlying EC functions are shared by several
|
||||
* crypto operations, some of which do not use the countermeasures.
|
||||
* The high-order 31 bits must be uniformly random. The entropy from
|
||||
* these bits is used by the countermeasures.
|
||||
*
|
||||
* @return byte[] the signature.
|
||||
*/
|
||||
private static native byte[] signDigest(byte[] digest, byte[] s,
|
||||
byte[] encodedParams, byte[] seed, int timing)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Verifies the signed digest using the public key.
|
||||
*
|
||||
* @param signature the signature to be verified. It is encoded
|
||||
* as a concatenation of the key's R and S values.
|
||||
* @param digest the digest to be used.
|
||||
* @param w the public key's W point (in uncompressed form).
|
||||
* @param encodedParams the curve's DER encoded object identifier.
|
||||
*
|
||||
* @return boolean true if the signature is successfully verified.
|
||||
*/
|
||||
private static native boolean verifySignedDigest(byte[] signature,
|
||||
byte[] digest, byte[] w, byte[] encodedParams)
|
||||
throws GeneralSecurityException;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
ecSpec = ECUtil.getECParameterSpec(null, ecParams);
|
||||
if (ecSpec == null) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Unsupported curve: " + params);
|
||||
"Curve not supported: " + params);
|
||||
}
|
||||
} else if (params instanceof ECGenParameterSpec) {
|
||||
String name = ((ECGenParameterSpec) params).getName();
|
||||
@ -126,29 +126,13 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
ecParams.init(ecSpec);
|
||||
} catch (InvalidParameterSpecException ex) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Unsupported curve: " + ecSpec.toString());
|
||||
"Curve not supported: " + ecSpec.toString());
|
||||
}
|
||||
|
||||
// Check if the java implementation supports this curve
|
||||
if (ECOperations.forParameters(ecSpec).isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the native library supported this curve, if available
|
||||
if (SunEC.isNativeDisabled()) {
|
||||
if (ECOperations.forParameters(ecSpec).isEmpty()) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Unsupported curve: " + ecSpec.toString());
|
||||
}
|
||||
|
||||
byte[] encodedParams;
|
||||
try {
|
||||
encodedParams = ecParams.getEncoded();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
if (!isCurveSupported(encodedParams)) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Unsupported curve: " + ecParams.toString());
|
||||
"Curve not supported: " + ecSpec.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,15 +152,8 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
} catch (Exception ex) {
|
||||
throw new ProviderException(ex);
|
||||
}
|
||||
if (SunEC.isNativeDisabled()) {
|
||||
throw new ProviderException("Legacy SunEC curve disabled: " +
|
||||
params.toString());
|
||||
}
|
||||
try {
|
||||
return generateKeyPairNative(random);
|
||||
} catch (Exception ex) {
|
||||
throw new ProviderException(ex);
|
||||
}
|
||||
throw new ProviderException("Curve not supported: " +
|
||||
params.toString());
|
||||
}
|
||||
|
||||
private byte[] generatePrivateScalar(SecureRandom random,
|
||||
@ -231,32 +208,6 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
return Optional.of(new KeyPair(publicKey, privateKey));
|
||||
}
|
||||
|
||||
private KeyPair generateKeyPairNative(SecureRandom random)
|
||||
throws Exception {
|
||||
|
||||
ECParameterSpec ecParams = (ECParameterSpec) params;
|
||||
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, ecParams);
|
||||
|
||||
// seed is twice the key size (in bytes) plus 1
|
||||
byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
|
||||
random.nextBytes(seed);
|
||||
Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
|
||||
|
||||
// The 'params' object supplied above is equivalent to the native
|
||||
// one so there is no need to fetch it.
|
||||
// keyBytes[0] is the encoding of the native private key
|
||||
BigInteger s = new BigInteger(1, (byte[]) keyBytes[0]);
|
||||
|
||||
PrivateKey privateKey = new ECPrivateKeyImpl(s, ecParams);
|
||||
|
||||
// keyBytes[1] is the encoding of the native public key
|
||||
byte[] pubKey = (byte[]) keyBytes[1];
|
||||
ECPoint w = ECUtil.decodePoint(pubKey, ecParams.getCurve());
|
||||
PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
|
||||
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
}
|
||||
|
||||
private void checkKeySize(int keySize) throws InvalidParameterException {
|
||||
if (keySize < KEY_SIZE_MIN) {
|
||||
throw new InvalidParameterException
|
||||
@ -268,24 +219,4 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
}
|
||||
this.keySize = keySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the curve in the encoded parameters is supported by the
|
||||
* native implementation. Some curve operations will be performed by the
|
||||
* Java implementation, but not all of them. So native support is still
|
||||
* required for all curves.
|
||||
*
|
||||
* @param encodedParams encoded parameters in the same form accepted
|
||||
* by generateECKeyPair
|
||||
* @return true if and only if generateECKeyPair will succeed for
|
||||
* the supplied parameters
|
||||
*/
|
||||
private static native boolean isCurveSupported(byte[] encodedParams);
|
||||
|
||||
/*
|
||||
* Generates the keypair and returns a 2-element array of encoding bytes.
|
||||
* The first one is for the private key, the second for the public key.
|
||||
*/
|
||||
private static native Object[] generateECKeyPair(int keySize,
|
||||
byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
|
||||
}
|
||||
|
@ -31,9 +31,11 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Provider;
|
||||
import java.security.ProviderException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import sun.security.ec.ed.EdDSAAlgorithmParameters;
|
||||
@ -41,6 +43,7 @@ import sun.security.ec.ed.EdDSAKeyFactory;
|
||||
import sun.security.ec.ed.EdDSAKeyPairGenerator;
|
||||
import sun.security.ec.ed.EdDSASignature;
|
||||
import sun.security.util.CurveDB;
|
||||
import sun.security.util.KnownOIDs;
|
||||
import sun.security.util.NamedCurve;
|
||||
|
||||
import static sun.security.util.SecurityConstants.PROVIDER_VER;
|
||||
@ -48,54 +51,11 @@ import static sun.security.util.SecurityProviderConstants.*;
|
||||
|
||||
/**
|
||||
* Provider class for the Elliptic Curve provider.
|
||||
* Supports EC keypair and parameter generation, ECDSA signing and
|
||||
* ECDH key agreement.
|
||||
*
|
||||
* IMPLEMENTATION NOTE:
|
||||
* The Java classes in this provider access a native ECC implementation
|
||||
* via JNI to a C++ wrapper class which in turn calls C functions.
|
||||
* The Java classes are packaged into the jdk.crypto.sunec module and the
|
||||
* C++ and C functions are packaged into libsunec.so or sunec.dll in the
|
||||
* JRE native libraries directory. If the native library is not present
|
||||
* then this provider is registered with support for fewer ECC algorithms
|
||||
* (KeyPairGenerator, Signature and KeyAgreement are omitted).
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public final class SunEC extends Provider {
|
||||
|
||||
private static final long serialVersionUID = -2279741672933606418L;
|
||||
|
||||
// This flag is true if the native library is disabled or not loaded.
|
||||
private static boolean disableNative = true;
|
||||
|
||||
static {
|
||||
String s = sun.security.action.GetPropertyAction.privilegedGetProperty(
|
||||
"jdk.sunec.disableNative");
|
||||
if (s != null && s.equalsIgnoreCase("false")) {
|
||||
disableNative = false;
|
||||
}
|
||||
|
||||
// If native is enabled, verify the library is available.
|
||||
if (!disableNative) {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("sunec"); // check for native library
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
disableNative = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if native library support is disabled.
|
||||
static boolean isNativeDisabled() {
|
||||
return SunEC.disableNative;
|
||||
}
|
||||
|
||||
private static class ProviderServiceA extends ProviderService {
|
||||
ProviderServiceA(Provider p, String type, String algo, String cn,
|
||||
HashMap<String, String> attrs) {
|
||||
@ -258,17 +218,11 @@ public final class SunEC extends Provider {
|
||||
boolean firstCurve = true;
|
||||
StringBuilder names = new StringBuilder();
|
||||
|
||||
Collection<? extends NamedCurve> supportedCurves;
|
||||
if (SunEC.isNativeDisabled()) {
|
||||
supportedCurves = Collections.unmodifiableList(List.of(
|
||||
CurveDB.lookup("secp256r1"),
|
||||
CurveDB.lookup("secp384r1"),
|
||||
CurveDB.lookup("secp521r1")));
|
||||
} else {
|
||||
supportedCurves = CurveDB.getSupportedCurves();
|
||||
}
|
||||
|
||||
for (NamedCurve namedCurve : supportedCurves) {
|
||||
for (NamedCurve namedCurve :
|
||||
List.of(
|
||||
CurveDB.lookup("secp256r1"),
|
||||
CurveDB.lookup("secp384r1"),
|
||||
CurveDB.lookup("secp521r1"))) {
|
||||
if (!firstCurve) {
|
||||
names.append("|");
|
||||
} else {
|
||||
@ -380,7 +334,6 @@ public final class SunEC extends Provider {
|
||||
HashMap<String, String> ATTRS = new HashMap<>(1);
|
||||
ATTRS.put("ImplementedIn", "Software");
|
||||
|
||||
/* XDH does not require native implementation */
|
||||
putService(new ProviderService(this, "KeyFactory",
|
||||
"XDH", "sun.security.ec.XDHKeyFactory", null, ATTRS));
|
||||
putService(new ProviderServiceA(this, "KeyFactory",
|
||||
@ -414,7 +367,6 @@ public final class SunEC extends Provider {
|
||||
HashMap<String, String> ATTRS = new HashMap<>(1);
|
||||
ATTRS.put("ImplementedIn", "Software");
|
||||
|
||||
/* EdDSA does not require native implementation */
|
||||
putService(new ProviderService(this, "KeyFactory",
|
||||
"EdDSA", "sun.security.ec.ed.EdDSAKeyFactory", null, ATTRS));
|
||||
putService(new ProviderServiceA(this, "KeyFactory",
|
||||
|
@ -1,599 +0,0 @@
|
||||
## Mozilla Elliptic Curve Cryptography (ECC)
|
||||
|
||||
### Mozilla ECC Notice
|
||||
|
||||
You are receiving a
|
||||
[copy](http://hg.openjdk.java.net/jdk/jdk/file/tip/src/jdk.crypto.ec/share/native/libsunec/impl)
|
||||
of the Elliptic Curve Cryptography library in source form or object code.
|
||||
|
||||
```
|
||||
The terms of the Oracle license do NOT apply to the Elliptic Curve Cryptography
|
||||
library; it is licensed under the following license, separately from the Oracle
|
||||
programs you received. If you do not wish to install the Elliptic Curve
|
||||
Cryptography library, you may delete the Elliptic Curve Cryptography library by
|
||||
removing:
|
||||
|
||||
Linux: $(JAVA_HOME)/lib/libsunec.so
|
||||
macOS: $(JAVA_HOME)/lib/libsunec.dylib
|
||||
Windows: $(JAVA_HOME)\bin\sunec.dll
|
||||
|
||||
```
|
||||
|
||||
#### Mozilla ECC Library Removal Impact
|
||||
```
|
||||
The Java Cryptographic Service SunEC Provider uses the Mozilla ECC library. If
|
||||
this native library is removed, the following algorithms will no longer be
|
||||
available from the SunEC provider using the JCA/JCE APIs:
|
||||
|
||||
KeyPairGenerator: EC
|
||||
KeyAgreement: ECDH
|
||||
Signature: names that include *withECDSA*
|
||||
|
||||
```
|
||||
|
||||
#### Written Offer for Source Code
|
||||
|
||||
```
|
||||
For third party technology that you receive from Oracle in binary form which
|
||||
is licensed under an open source license that gives you the right to receive
|
||||
the source code for that binary, you can also receive a copy of the source
|
||||
code on physical media by submitting a written request to:
|
||||
|
||||
Oracle America, Inc.
|
||||
Attn: Associate General Counsel,
|
||||
Development and Engineering Legal
|
||||
500 Oracle Parkway, 10th Floor
|
||||
Redwood Shores, CA 94065
|
||||
|
||||
Your request should include:
|
||||
```
|
||||
|
||||
* The name of the component or binary file(s) for which you are requesting
|
||||
the source code
|
||||
* The name and version number of the Oracle product containing the binary
|
||||
* The date you received the Oracle product
|
||||
* Your name
|
||||
* Your company name (if applicable)
|
||||
* Your return mailing address and email and
|
||||
* A telephone number in the event we need to reach you.
|
||||
|
||||
```
|
||||
We may charge you a fee to cover the cost of physical media and processing.
|
||||
Your request must be sent (i) within three (3) years of the date you received
|
||||
the Oracle product that included the component or binary file(s) that are the
|
||||
subject of your request, or (ii) in the case of code licensed under the GPL
|
||||
v3, for as long as Oracle offers spare parts or customer support for that
|
||||
product model.
|
||||
|
||||
```
|
||||
|
||||
### Mozilla ECC License
|
||||
```
|
||||
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 and
|
||||
Douglas Stebila, Sun Microsystems Laboratories
|
||||
|
||||
The Elliptic Curve Cryptography Library is subject to GNU Lesser Public License
|
||||
Version 2.1.
|
||||
```
|
||||
|
||||
#### LGPL 2.1
|
||||
```
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
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
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
```
|
||||
|
@ -1,527 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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 General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include "jni_util.h"
|
||||
#include "impl/ecc_impl.h"
|
||||
#include "sun_security_ec_ECDHKeyAgreement.h"
|
||||
#include "sun_security_ec_ECKeyPairGenerator.h"
|
||||
#include "sun_security_ec_ECDSASignature.h"
|
||||
|
||||
#define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
|
||||
#define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
|
||||
"java/security/InvalidAlgorithmParameterException"
|
||||
#define INVALID_PARAMETER_EXCEPTION \
|
||||
"java/security/InvalidParameterException"
|
||||
#define KEY_EXCEPTION "java/security/KeyException"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
* Declare library specific JNI_Onload entry if static build
|
||||
*/
|
||||
DEF_STATIC_JNI_OnLoad
|
||||
|
||||
/*
|
||||
* Throws an arbitrary Java exception.
|
||||
*/
|
||||
void ThrowException(JNIEnv *env, const char *exceptionName)
|
||||
{
|
||||
jclass exceptionClazz = env->FindClass(exceptionName);
|
||||
if (exceptionClazz != NULL) {
|
||||
env->ThrowNew(exceptionClazz, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deep free of the ECParams struct
|
||||
*/
|
||||
void FreeECParams(ECParams *ecparams, jboolean freeStruct)
|
||||
{
|
||||
// Use B_FALSE to free the SECItem->data element, but not the SECItem itself
|
||||
// Use B_TRUE to free both
|
||||
|
||||
SECITEM_FreeItem(&ecparams->fieldID.u.prime, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->curve.a, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->curve.b, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->curve.seed, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->base, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->order, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE);
|
||||
SECITEM_FreeItem(&ecparams->curveOID, B_FALSE);
|
||||
if (freeStruct)
|
||||
free(ecparams);
|
||||
}
|
||||
|
||||
jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)
|
||||
{
|
||||
SECItem *s = (SECItem *)hSECItem;
|
||||
|
||||
jbyteArray jEncodedBytes = env->NewByteArray(s->len);
|
||||
if (jEncodedBytes == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
// Copy bytes from a native SECItem buffer to Java byte array
|
||||
env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);
|
||||
if (env->ExceptionCheck()) { // should never happen
|
||||
return NULL;
|
||||
}
|
||||
return jEncodedBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_security_ec_ECKeyPairGenerator
|
||||
* Method: isCurveSupported
|
||||
* Signature: ([B)Z
|
||||
*/
|
||||
JNIEXPORT jboolean
|
||||
JNICALL Java_sun_security_ec_ECKeyPairGenerator_isCurveSupported
|
||||
(JNIEnv *env, jclass clazz, jbyteArray encodedParams)
|
||||
{
|
||||
SECKEYECParams params_item;
|
||||
ECParams *ecparams = NULL;
|
||||
jboolean result = JNI_FALSE;
|
||||
|
||||
// The curve is supported if we can get parameters for it
|
||||
params_item.len = env->GetArrayLength(encodedParams);
|
||||
params_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
|
||||
if (params_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Fill a new ECParams using the supplied OID
|
||||
if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
|
||||
/* bad curve OID */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// If we make it to here, then the curve is supported
|
||||
result = JNI_TRUE;
|
||||
|
||||
cleanup:
|
||||
{
|
||||
if (params_item.data) {
|
||||
env->ReleaseByteArrayElements(encodedParams,
|
||||
(jbyte *) params_item.data, JNI_ABORT);
|
||||
}
|
||||
if (ecparams) {
|
||||
FreeECParams(ecparams, true);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_security_ec_ECKeyPairGenerator
|
||||
* Method: generateECKeyPair
|
||||
* Signature: (I[B[B)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray
|
||||
JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
|
||||
(JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
|
||||
{
|
||||
ECPrivateKey *privKey = NULL; // contains both public and private values
|
||||
ECParams *ecparams = NULL;
|
||||
SECKEYECParams params_item;
|
||||
jint jSeedLength;
|
||||
jbyte* pSeedBuffer = NULL;
|
||||
jobjectArray result = NULL;
|
||||
jclass baCls = NULL;
|
||||
jbyteArray jba;
|
||||
|
||||
// Initialize the ECParams struct
|
||||
params_item.len = env->GetArrayLength(encodedParams);
|
||||
params_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
|
||||
if (params_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Fill a new ECParams using the supplied OID
|
||||
if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
|
||||
/* bad curve OID */
|
||||
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Copy seed from Java to native buffer
|
||||
jSeedLength = env->GetArrayLength(seed);
|
||||
pSeedBuffer = new jbyte[jSeedLength];
|
||||
env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
|
||||
|
||||
// Generate the new keypair (using the supplied seed)
|
||||
if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,
|
||||
jSeedLength, 0) != SECSuccess) {
|
||||
ThrowException(env, KEY_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
jboolean isCopy;
|
||||
baCls = env->FindClass("[B");
|
||||
if (baCls == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
result = env->NewObjectArray(2, baCls, NULL);
|
||||
if (result == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
jba = getEncodedBytes(env, &(privKey->privateValue));
|
||||
if (jba == NULL) {
|
||||
result = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
env->SetObjectArrayElement(result, 0, jba); // big integer
|
||||
if (env->ExceptionCheck()) { // should never happen
|
||||
result = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
jba = getEncodedBytes(env, &(privKey->publicValue));
|
||||
if (jba == NULL) {
|
||||
result = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
env->SetObjectArrayElement(result, 1, jba); // encoded ec point
|
||||
if (env->ExceptionCheck()) { // should never happen
|
||||
result = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
{
|
||||
if (params_item.data) {
|
||||
env->ReleaseByteArrayElements(encodedParams,
|
||||
(jbyte *) params_item.data, JNI_ABORT);
|
||||
}
|
||||
if (ecparams) {
|
||||
FreeECParams(ecparams, true);
|
||||
}
|
||||
if (privKey) {
|
||||
FreeECParams(&privKey->ecParams, false);
|
||||
SECITEM_FreeItem(&privKey->version, B_FALSE);
|
||||
SECITEM_FreeItem(&privKey->privateValue, B_FALSE);
|
||||
SECITEM_FreeItem(&privKey->publicValue, B_FALSE);
|
||||
free(privKey);
|
||||
}
|
||||
|
||||
if (pSeedBuffer) {
|
||||
delete [] pSeedBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_security_ec_ECDSASignature
|
||||
* Method: signDigest
|
||||
* Signature: ([B[B[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray
|
||||
JNICALL Java_sun_security_ec_ECDSASignature_signDigest
|
||||
(JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed, jint timing)
|
||||
{
|
||||
jbyte* pDigestBuffer = NULL;
|
||||
jint jDigestLength = env->GetArrayLength(digest);
|
||||
jbyteArray jSignedDigest = NULL;
|
||||
|
||||
SECItem signature_item;
|
||||
jbyte* pSignedDigestBuffer = NULL;
|
||||
jbyteArray temp;
|
||||
|
||||
jint jSeedLength = env->GetArrayLength(seed);
|
||||
jbyte* pSeedBuffer = NULL;
|
||||
|
||||
// Copy digest from Java to native buffer
|
||||
pDigestBuffer = new jbyte[jDigestLength];
|
||||
env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
|
||||
SECItem digest_item;
|
||||
digest_item.data = (unsigned char *) pDigestBuffer;
|
||||
digest_item.len = jDigestLength;
|
||||
|
||||
ECPrivateKey privKey;
|
||||
privKey.privateValue.data = NULL;
|
||||
|
||||
// Initialize the ECParams struct
|
||||
ECParams *ecparams = NULL;
|
||||
SECKEYECParams params_item;
|
||||
params_item.len = env->GetArrayLength(encodedParams);
|
||||
params_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
|
||||
if (params_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Fill a new ECParams using the supplied OID
|
||||
if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
|
||||
/* bad curve OID */
|
||||
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Extract private key data
|
||||
privKey.ecParams = *ecparams; // struct assignment
|
||||
privKey.privateValue.len = env->GetArrayLength(privateKey);
|
||||
privKey.privateValue.data =
|
||||
(unsigned char *) env->GetByteArrayElements(privateKey, 0);
|
||||
if (privKey.privateValue.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Prepare a buffer for the signature (twice the key length)
|
||||
pSignedDigestBuffer = new jbyte[ecparams->order.len * 2];
|
||||
signature_item.data = (unsigned char *) pSignedDigestBuffer;
|
||||
signature_item.len = ecparams->order.len * 2;
|
||||
|
||||
// Copy seed from Java to native buffer
|
||||
pSeedBuffer = new jbyte[jSeedLength];
|
||||
env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
|
||||
|
||||
// Sign the digest (using the supplied seed)
|
||||
if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
|
||||
(unsigned char *) pSeedBuffer, jSeedLength, 0, timing) != SECSuccess) {
|
||||
ThrowException(env, KEY_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Create new byte array
|
||||
temp = env->NewByteArray(signature_item.len);
|
||||
if (temp == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Copy data from native buffer
|
||||
env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer);
|
||||
jSignedDigest = temp;
|
||||
|
||||
cleanup:
|
||||
{
|
||||
if (params_item.data) {
|
||||
env->ReleaseByteArrayElements(encodedParams,
|
||||
(jbyte *) params_item.data, JNI_ABORT);
|
||||
}
|
||||
if (privKey.privateValue.data) {
|
||||
env->ReleaseByteArrayElements(privateKey,
|
||||
(jbyte *) privKey.privateValue.data, JNI_ABORT);
|
||||
}
|
||||
if (pDigestBuffer) {
|
||||
delete [] pDigestBuffer;
|
||||
}
|
||||
if (pSignedDigestBuffer) {
|
||||
delete [] pSignedDigestBuffer;
|
||||
}
|
||||
if (pSeedBuffer) {
|
||||
delete [] pSeedBuffer;
|
||||
}
|
||||
if (ecparams) {
|
||||
FreeECParams(ecparams, true);
|
||||
}
|
||||
}
|
||||
|
||||
return jSignedDigest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_security_ec_ECDSASignature
|
||||
* Method: verifySignedDigest
|
||||
* Signature: ([B[B[B[B)Z
|
||||
*/
|
||||
JNIEXPORT jboolean
|
||||
JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
|
||||
(JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)
|
||||
{
|
||||
jboolean isValid = false;
|
||||
|
||||
// Copy signedDigest from Java to native buffer
|
||||
jbyte* pSignedDigestBuffer = NULL;
|
||||
jint jSignedDigestLength = env->GetArrayLength(signedDigest);
|
||||
pSignedDigestBuffer = new jbyte[jSignedDigestLength];
|
||||
env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength,
|
||||
pSignedDigestBuffer);
|
||||
SECItem signature_item;
|
||||
signature_item.data = (unsigned char *) pSignedDigestBuffer;
|
||||
signature_item.len = jSignedDigestLength;
|
||||
|
||||
// Copy digest from Java to native buffer
|
||||
jbyte* pDigestBuffer = NULL;
|
||||
jint jDigestLength = env->GetArrayLength(digest);
|
||||
pDigestBuffer = new jbyte[jDigestLength];
|
||||
env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
|
||||
SECItem digest_item;
|
||||
digest_item.data = (unsigned char *) pDigestBuffer;
|
||||
digest_item.len = jDigestLength;
|
||||
|
||||
// Extract public key data
|
||||
ECPublicKey pubKey;
|
||||
pubKey.publicValue.data = NULL;
|
||||
ECParams *ecparams = NULL;
|
||||
SECKEYECParams params_item;
|
||||
|
||||
// Initialize the ECParams struct
|
||||
params_item.len = env->GetArrayLength(encodedParams);
|
||||
params_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
|
||||
if (params_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Fill a new ECParams using the supplied OID
|
||||
if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
|
||||
/* bad curve OID */
|
||||
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
pubKey.ecParams = *ecparams; // struct assignment
|
||||
pubKey.publicValue.len = env->GetArrayLength(publicKey);
|
||||
pubKey.publicValue.data =
|
||||
(unsigned char *) env->GetByteArrayElements(publicKey, 0);
|
||||
|
||||
if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)
|
||||
!= SECSuccess) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
|
||||
cleanup:
|
||||
{
|
||||
if (params_item.data)
|
||||
env->ReleaseByteArrayElements(encodedParams,
|
||||
(jbyte *) params_item.data, JNI_ABORT);
|
||||
|
||||
if (pubKey.publicValue.data)
|
||||
env->ReleaseByteArrayElements(publicKey,
|
||||
(jbyte *) pubKey.publicValue.data, JNI_ABORT);
|
||||
|
||||
if (ecparams)
|
||||
FreeECParams(ecparams, true);
|
||||
|
||||
if (pSignedDigestBuffer)
|
||||
delete [] pSignedDigestBuffer;
|
||||
|
||||
if (pDigestBuffer)
|
||||
delete [] pDigestBuffer;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_security_ec_ECDHKeyAgreement
|
||||
* Method: deriveKey
|
||||
* Signature: ([B[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray
|
||||
JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
|
||||
(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)
|
||||
{
|
||||
jbyteArray jSecret = NULL;
|
||||
ECParams *ecparams = NULL;
|
||||
SECItem privateValue_item;
|
||||
privateValue_item.data = NULL;
|
||||
SECItem publicValue_item;
|
||||
publicValue_item.data = NULL;
|
||||
SECKEYECParams params_item;
|
||||
params_item.data = NULL;
|
||||
|
||||
// Extract private key value
|
||||
privateValue_item.len = env->GetArrayLength(privateKey);
|
||||
privateValue_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(privateKey, 0);
|
||||
if (privateValue_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Extract public key value
|
||||
publicValue_item.len = env->GetArrayLength(publicKey);
|
||||
publicValue_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(publicKey, 0);
|
||||
if (publicValue_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Initialize the ECParams struct
|
||||
params_item.len = env->GetArrayLength(encodedParams);
|
||||
params_item.data =
|
||||
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
|
||||
if (params_item.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Fill a new ECParams using the supplied OID
|
||||
if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
|
||||
/* bad curve OID */
|
||||
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Prepare a buffer for the secret
|
||||
SECItem secret_item;
|
||||
secret_item.data = NULL;
|
||||
secret_item.len = ecparams->order.len * 2;
|
||||
|
||||
if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,
|
||||
&secret_item, 0) != SECSuccess) {
|
||||
ThrowException(env, ILLEGAL_STATE_EXCEPTION);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Create new byte array
|
||||
jSecret = env->NewByteArray(secret_item.len);
|
||||
if (jSecret == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Copy bytes from the SECItem buffer to a Java byte array
|
||||
env->SetByteArrayRegion(jSecret, 0, secret_item.len,
|
||||
(jbyte *)secret_item.data);
|
||||
|
||||
// Free the SECItem data buffer
|
||||
SECITEM_FreeItem(&secret_item, B_FALSE);
|
||||
|
||||
cleanup:
|
||||
{
|
||||
if (privateValue_item.data)
|
||||
env->ReleaseByteArrayElements(privateKey,
|
||||
(jbyte *) privateValue_item.data, JNI_ABORT);
|
||||
|
||||
if (publicValue_item.data)
|
||||
env->ReleaseByteArrayElements(publicKey,
|
||||
(jbyte *) publicValue_item.data, JNI_ABORT);
|
||||
|
||||
if (params_item.data)
|
||||
env->ReleaseByteArrayElements(encodedParams,
|
||||
(jbyte *) params_item.data, JNI_ABORT);
|
||||
|
||||
if (ecparams)
|
||||
FreeECParams(ecparams, true);
|
||||
}
|
||||
|
||||
return jSecret;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
File diff suppressed because it is too large
Load Diff
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef __ec_h_
|
||||
#define __ec_h_
|
||||
|
||||
#define EC_DEBUG 0
|
||||
#define EC_POINT_FORM_COMPRESSED_Y0 0x02
|
||||
#define EC_POINT_FORM_COMPRESSED_Y1 0x03
|
||||
#define EC_POINT_FORM_UNCOMPRESSED 0x04
|
||||
#define EC_POINT_FORM_HYBRID_Y0 0x06
|
||||
#define EC_POINT_FORM_HYBRID_Y1 0x07
|
||||
|
||||
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
|
||||
#define SECG_CURVE_OID_TOTAL_LEN 7
|
||||
#define BRAINPOOL_CURVE_OID_TOTAL_LEN 11
|
||||
|
||||
#endif /* __ec_h_ */
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for binary polynomial field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _EC2_H
|
||||
#define _EC2_H
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses Montgomery projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group, int timing);
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). */
|
||||
mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* _EC2_H */
|
@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for binary polynomial field curves.
|
||||
*
|
||||
* 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):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Fast reduction for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 6;
|
||||
|
||||
/* u[5] only has 6 significant bits */
|
||||
z = u[5];
|
||||
u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[3];
|
||||
u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[2] >> 35; /* z only has 29 significant bits */
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[5] = u[4] = u[3] = 0;
|
||||
u[2] ^= z << 35;
|
||||
#else
|
||||
if (MP_USED(r) < 11) {
|
||||
MP_CHECKOK(s_mp_pad(r, 11));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 11;
|
||||
|
||||
/* u[11] only has 6 significant bits */
|
||||
z = u[10];
|
||||
u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[4] ^= (z << 29);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 28) ^ (z >> 29);
|
||||
u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[3] ^= (z << 29);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 28) ^ (z >> 29);
|
||||
u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[2] ^= (z << 29);
|
||||
z = u[7];
|
||||
u[3] ^= (z >> 28) ^ (z >> 29);
|
||||
u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[1] ^= (z << 29);
|
||||
z = u[6];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29);
|
||||
u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[0] ^= (z << 29);
|
||||
z = u[5] >> 3; /* z only has 29 significant bits */
|
||||
u[1] ^= (z >> 25) ^ (z >> 26);
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0;
|
||||
u[5] ^= z << 3;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 3) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
if (MP_USED(a) < 6) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 12) {
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
}
|
||||
MP_USED(r) = 12;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
#endif
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 163-bit curve. Assumes
|
||||
* reduction polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0;
|
||||
mp_digit rm[6];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_163_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
#endif
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
#endif
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
MP_USED(r) = 6;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3);
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1,
|
||||
b3 ^ b0);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6);
|
||||
MP_DIGIT(r, 8) ^= rm[5];
|
||||
MP_DIGIT(r, 7) ^= rm[4];
|
||||
MP_DIGIT(r, 6) ^= rm[3];
|
||||
MP_DIGIT(r, 5) ^= rm[2];
|
||||
MP_DIGIT(r, 4) ^= rm[1];
|
||||
MP_DIGIT(r, 3) ^= rm[0];
|
||||
MP_USED(r) = 12;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 163-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m163(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_163_mod;
|
||||
group->meth->field_mul = &ec_GF2m_163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_163_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for binary polynomial field curves.
|
||||
*
|
||||
* 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):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Fast reduction for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 7;
|
||||
|
||||
/* u[6] only has 2 significant bits */
|
||||
z = u[6];
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 63);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 50);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 63);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 50);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 63);
|
||||
z = u[3] >> 1; /* z only has 63 significant bits */
|
||||
u[1] ^= (z >> 49);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 1;
|
||||
#else
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 13;
|
||||
|
||||
/* u[12] only has 2 significant bits */
|
||||
z = u[12];
|
||||
u[6] ^= (z << 14) ^ (z >> 1);
|
||||
u[5] ^= (z << 31);
|
||||
z = u[11];
|
||||
u[6] ^= (z >> 18);
|
||||
u[5] ^= (z << 14) ^ (z >> 1);
|
||||
u[4] ^= (z << 31);
|
||||
z = u[10];
|
||||
u[5] ^= (z >> 18);
|
||||
u[4] ^= (z << 14) ^ (z >> 1);
|
||||
u[3] ^= (z << 31);
|
||||
z = u[9];
|
||||
u[4] ^= (z >> 18);
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 31);
|
||||
z = u[8];
|
||||
u[3] ^= (z >> 18);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 31);
|
||||
z = u[7];
|
||||
u[2] ^= (z >> 18);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 31);
|
||||
z = u[6] >> 1; /* z only has 31 significant bits */
|
||||
u[1] ^= (z >> 17);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[12] = u[11] = u[10] = u[9] = u[8] = u[7] = 0;
|
||||
u[6] ^= z << 1;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
MP_USED(r) = 7;
|
||||
#else
|
||||
if (MP_USED(a) < 7) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
MP_USED(r) = 13;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
#endif
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 193-bit curve. Assumes
|
||||
* reduction polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, b6 = 0, b5 = 0, b4 = 0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_193_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 14));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 8, a6, a5, a4, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b3, b6 ^ b2, b5 ^ b1,
|
||||
b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7);
|
||||
rm[6] ^= MP_DIGIT(r, 6);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 14;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 193-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m193(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_193_mod;
|
||||
group->meth->field_mul = &ec_GF2m_193_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_193_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for binary polynomial field curves.
|
||||
*
|
||||
* 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):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Fast reduction for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 8;
|
||||
|
||||
/* u[7] only has 18 significant bits */
|
||||
z = u[7];
|
||||
u[4] ^= (z << 33) ^ (z >> 41);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[6];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 33) ^ (z >> 41);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 31);
|
||||
u[2] ^= (z << 33) ^ (z >> 41);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 31);
|
||||
u[1] ^= (z << 33) ^ (z >> 41);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[3] >> 41; /* z only has 23 significant bits */
|
||||
u[1] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[7] = u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 41;
|
||||
#else
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 15;
|
||||
|
||||
/* u[14] only has 18 significant bits */
|
||||
z = u[14];
|
||||
u[9] ^= (z << 1);
|
||||
u[7] ^= (z >> 9);
|
||||
u[6] ^= (z << 23);
|
||||
z = u[13];
|
||||
u[9] ^= (z >> 31);
|
||||
u[8] ^= (z << 1);
|
||||
u[6] ^= (z >> 9);
|
||||
u[5] ^= (z << 23);
|
||||
z = u[12];
|
||||
u[8] ^= (z >> 31);
|
||||
u[7] ^= (z << 1);
|
||||
u[5] ^= (z >> 9);
|
||||
u[4] ^= (z << 23);
|
||||
z = u[11];
|
||||
u[7] ^= (z >> 31);
|
||||
u[6] ^= (z << 1);
|
||||
u[4] ^= (z >> 9);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[10];
|
||||
u[6] ^= (z >> 31);
|
||||
u[5] ^= (z << 1);
|
||||
u[3] ^= (z >> 9);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 31);
|
||||
u[4] ^= (z << 1);
|
||||
u[2] ^= (z >> 9);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 1);
|
||||
u[1] ^= (z >> 9);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[7] >> 9; /* z only has 23 significant bits */
|
||||
u[3] ^= (z >> 22);
|
||||
u[2] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[14] = u[13] = u[12] = u[11] = u[10] = u[9] = u[8] = 0;
|
||||
u[7] ^= z << 9;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
MP_USED(r) = 8;
|
||||
#else
|
||||
if (MP_USED(a) < 8) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
MP_USED(r) = 15;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[14] = gf2m_SQR0(v[7]);
|
||||
u[13] = gf2m_SQR1(v[6]);
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
#endif
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 233-bit curve. Assumes
|
||||
* reduction polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a7 = 0, a6 = 0, a5 = 0, a4 = 0, b7 = 0, b6 = 0, b5 = 0, b4 =
|
||||
0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_233_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
b7 = MP_DIGIT(b, 7);
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 16));
|
||||
s_bmul_4x4(MP_DIGITS(r) + 8, a7, a6, a5, a4, b7, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a7 ^ a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b7 ^ b3,
|
||||
b6 ^ b2, b5 ^ b1, b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7) ^ MP_DIGIT(r, 15);
|
||||
rm[6] ^= MP_DIGIT(r, 6) ^ MP_DIGIT(r, 14);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 16;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 233-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m233(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_233_mod;
|
||||
group->meth->field_mul = &ec_GF2m_233_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_233_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for binary polynomial field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.2. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&tempx, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&tempy, FLAG(px)));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py+qy) / (px+qx), tempx = a + lambda^2
|
||||
* + lambda + px + qx */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, qx, &tempx, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qx = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = qx + qy / qx */
|
||||
MP_CHECKOK(group->meth->field_div(qy, qx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&lambda, qx, &lambda, group->meth));
|
||||
/* tempx = a + lambda^2 + lambda */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
}
|
||||
/* ry = (qx + tempx) * lambda + tempx + qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempy, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&tempy, qy, ry, group->meth));
|
||||
/* rx = tempx */
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy, FLAG(px)));
|
||||
/* nqy = qx+qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth));
|
||||
MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group));
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return group->point_add(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err
|
||||
ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&accr, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&tmp, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&pxt, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&pyt, FLAG(px)));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 + x*y */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x^2 + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
/* timing mitigation is not supported */
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) );
|
||||
if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for binary polynomial field curves.
|
||||
*
|
||||
* 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):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery
|
||||
* projective coordinates. Uses algorithm Mdouble in appendix of Lopez, J.
|
||||
* and Dahab, R. "Fast multiplication on elliptic curves over GF(2^m)
|
||||
* without precomputation". modified to not require precomputation of
|
||||
* c=b^{2^{m-1}}. */
|
||||
static mp_err
|
||||
gf2m_Mdouble(mp_int *x, mp_int *z, const ECGroup *group, int kmflag)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t1, kmflag));
|
||||
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x, &t1, z, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x, &t1, x, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in
|
||||
* Montgomery projective coordinates. Uses algorithm Madd in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". */
|
||||
static mp_err
|
||||
gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2,
|
||||
const ECGroup *group, int kmflag)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1, t2;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&t2) = 0;
|
||||
MP_CHECKOK(mp_init(&t1, kmflag));
|
||||
MP_CHECKOK(mp_init(&t2, kmflag));
|
||||
|
||||
MP_CHECKOK(mp_copy(x, &t1));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
mp_clear(&t2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". Returns: 0 on error 1 if return value
|
||||
* should be the point at infinity 2 otherwise */
|
||||
static int
|
||||
gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
|
||||
mp_int *x2, mp_int *z2, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int ret = 0;
|
||||
mp_int t3, t4, t5;
|
||||
|
||||
MP_DIGITS(&t3) = 0;
|
||||
MP_DIGITS(&t4) = 0;
|
||||
MP_DIGITS(&t5) = 0;
|
||||
MP_CHECKOK(mp_init(&t3, FLAG(x2)));
|
||||
MP_CHECKOK(mp_init(&t4, FLAG(x2)));
|
||||
MP_CHECKOK(mp_init(&t5, FLAG(x2)));
|
||||
|
||||
if (mp_cmp_z(z1) == 0) {
|
||||
mp_zero(x2);
|
||||
mp_zero(z2);
|
||||
ret = 1;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_z(z2) == 0) {
|
||||
MP_CHECKOK(mp_copy(x, x2));
|
||||
MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth));
|
||||
ret = 2;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_set_int(&t5, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth));
|
||||
|
||||
ret = 2;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t3);
|
||||
mp_clear(&t4);
|
||||
mp_clear(&t5);
|
||||
if (res == MP_OKAY) {
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast
|
||||
* multiplication on elliptic curves over GF(2^m) without
|
||||
* precomputation". Elliptic curve points P and R can be identical. Uses
|
||||
* Montgomery projective coordinates. The timing parameter is ignored
|
||||
* because this algorithm resists timing attacks by default. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group,
|
||||
int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int x1, x2, z1, z2;
|
||||
int i, j;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&x1, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&x2, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&z1, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&z2, FLAG(n)));
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */
|
||||
MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 =
|
||||
* x1^2 =
|
||||
* px^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2
|
||||
* =
|
||||
* px^4
|
||||
* +
|
||||
* b
|
||||
*/
|
||||
|
||||
/* find top-most bit and go one past it */
|
||||
i = MP_USED(n) - 1;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
while (!(MP_DIGITS(n)[i] & mask)) {
|
||||
mask >>= 1;
|
||||
j--;
|
||||
}
|
||||
mask >>= 1;
|
||||
j--;
|
||||
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
for (; j >= 0; j--) {
|
||||
if (MP_DIGITS(n)[i] & mask) {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group, FLAG(n)));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group, FLAG(n)));
|
||||
} else {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group, FLAG(n)));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group, FLAG(n)));
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group);
|
||||
if (i == 0) {
|
||||
res = MP_BADARG;
|
||||
goto CLEANUP;
|
||||
} else if (i == 1) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&x2, rx));
|
||||
MP_CHECKOK(mp_copy(&z2, ry));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int
|
||||
ec_twoTo(int e)
|
||||
{
|
||||
int a = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < e; i++) {
|
||||
a *= 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err
|
||||
ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in, int w)
|
||||
{
|
||||
mp_int k;
|
||||
mp_err res = MP_OKAY;
|
||||
int i, twowm1, mask;
|
||||
|
||||
twowm1 = ec_twoTo(w - 1);
|
||||
mask = 2 * twowm1 - 1;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_CHECKOK(mp_init_copy(&k, in));
|
||||
|
||||
i = 0;
|
||||
/* Compute wNAF form */
|
||||
while (mp_cmp_z(&k) > 0) {
|
||||
if (mp_isodd(&k)) {
|
||||
out[i] = MP_DIGIT(&k, 0) & mask;
|
||||
if (out[i] >= twowm1)
|
||||
out[i] -= 2 * twowm1;
|
||||
|
||||
/* Subtract off out[i]. Note mp_sub_d only works with
|
||||
* unsigned digits */
|
||||
if (out[i] >= 0) {
|
||||
mp_sub_d(&k, out[i], &k);
|
||||
} else {
|
||||
mp_add_d(&k, -(out[i]), &k);
|
||||
}
|
||||
} else {
|
||||
out[i] = 0;
|
||||
}
|
||||
mp_div_2(&k, &k);
|
||||
i++;
|
||||
}
|
||||
/* Zero out the remaining elements of the out array. */
|
||||
for (; i < bitsize + 1; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
return res;
|
||||
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _ECC_IMPL_H
|
||||
#define _ECC_IMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "ecl-exp.h"
|
||||
|
||||
/*
|
||||
* Multi-platform definitions
|
||||
*/
|
||||
#ifdef __linux__
|
||||
#define B_FALSE FALSE
|
||||
#define B_TRUE TRUE
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long ulong_t;
|
||||
typedef enum { B_FALSE, B_TRUE } boolean_t;
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
#include <stdint.h>
|
||||
#define B_FALSE FALSE
|
||||
#define B_TRUE TRUE
|
||||
typedef unsigned long ulong_t;
|
||||
typedef enum boolean { B_FALSE, B_TRUE } boolean_t;
|
||||
#endif /* _ALLBSD_SOURCE */
|
||||
|
||||
#ifdef AIX
|
||||
#define B_FALSE FALSE
|
||||
#define B_TRUE TRUE
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long ulong_t;
|
||||
#endif /* AIX */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long ulong_t;
|
||||
typedef enum boolean { B_FALSE, B_TRUE } boolean_t;
|
||||
#define strdup _strdup /* Replace POSIX name with ISO C++ name */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define EC_MAX_DIGEST_LEN 1024 /* max digest that can be signed */
|
||||
#define EC_MAX_POINT_LEN 145 /* max len of DER encoded Q */
|
||||
#define EC_MAX_VALUE_LEN 72 /* max len of ANSI X9.62 private value d */
|
||||
#define EC_MAX_SIG_LEN 144 /* max signature len for supported curves */
|
||||
#define EC_MIN_KEY_LEN 112 /* min key length in bits */
|
||||
#define EC_MAX_KEY_LEN 571 /* max key length in bits */
|
||||
#define EC_MAX_OID_LEN 10 /* max length of OID buffer */
|
||||
|
||||
/*
|
||||
* Various structures and definitions from NSS are here.
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define PORT_ArenaAlloc(a, n, f) kmem_alloc((n), (f))
|
||||
#define PORT_ArenaZAlloc(a, n, f) kmem_zalloc((n), (f))
|
||||
#define PORT_ArenaGrow(a, b, c, d) NULL
|
||||
#define PORT_ZAlloc(n, f) kmem_zalloc((n), (f))
|
||||
#define PORT_Alloc(n, f) kmem_alloc((n), (f))
|
||||
#else
|
||||
#define PORT_ArenaAlloc(a, n, f) malloc((n))
|
||||
#define PORT_ArenaZAlloc(a, n, f) calloc(1, (n))
|
||||
#define PORT_ArenaGrow(a, b, c, d) NULL
|
||||
#define PORT_ZAlloc(n, f) calloc(1, (n))
|
||||
#define PORT_Alloc(n, f) malloc((n))
|
||||
#endif
|
||||
|
||||
#define PORT_NewArena(b) (char *)12345
|
||||
#define PORT_ArenaMark(a) NULL
|
||||
#define PORT_ArenaUnmark(a, b)
|
||||
#define PORT_ArenaRelease(a, m)
|
||||
#define PORT_FreeArena(a, b)
|
||||
#define PORT_Strlen(s) strlen((s))
|
||||
#define PORT_SetError(e)
|
||||
|
||||
#define PRBool boolean_t
|
||||
#define PR_TRUE B_TRUE
|
||||
#define PR_FALSE B_FALSE
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define PORT_Assert ASSERT
|
||||
#define PORT_Memcpy(t, f, l) bcopy((f), (t), (l))
|
||||
#else
|
||||
#define PORT_Assert assert
|
||||
#define PORT_Memcpy(t, f, l) memcpy((t), (f), (l))
|
||||
#endif
|
||||
|
||||
#define CHECK_OK(func) if (func == NULL) goto cleanup
|
||||
#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
|
||||
|
||||
typedef enum {
|
||||
siBuffer = 0,
|
||||
siClearDataBuffer = 1,
|
||||
siCipherDataBuffer = 2,
|
||||
siDERCertBuffer = 3,
|
||||
siEncodedCertBuffer = 4,
|
||||
siDERNameBuffer = 5,
|
||||
siEncodedNameBuffer = 6,
|
||||
siAsciiNameString = 7,
|
||||
siAsciiString = 8,
|
||||
siDEROID = 9,
|
||||
siUnsignedInteger = 10,
|
||||
siUTCTime = 11,
|
||||
siGeneralizedTime = 12
|
||||
} SECItemType;
|
||||
|
||||
typedef struct SECItemStr SECItem;
|
||||
|
||||
struct SECItemStr {
|
||||
SECItemType type;
|
||||
unsigned char *data;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
typedef SECItem SECKEYECParams;
|
||||
|
||||
typedef enum { ec_params_explicit,
|
||||
ec_params_named
|
||||
} ECParamsType;
|
||||
|
||||
typedef enum { ec_field_GFp = 1,
|
||||
ec_field_GF2m
|
||||
} ECFieldType;
|
||||
|
||||
struct ECFieldIDStr {
|
||||
int size; /* field size in bits */
|
||||
ECFieldType type;
|
||||
union {
|
||||
SECItem prime; /* prime p for (GFp) */
|
||||
SECItem poly; /* irreducible binary polynomial for (GF2m) */
|
||||
} u;
|
||||
int k1; /* first coefficient of pentanomial or
|
||||
* the only coefficient of trinomial
|
||||
*/
|
||||
int k2; /* two remaining coefficients of pentanomial */
|
||||
int k3;
|
||||
};
|
||||
typedef struct ECFieldIDStr ECFieldID;
|
||||
|
||||
struct ECCurveStr {
|
||||
SECItem a; /* contains octet stream encoding of
|
||||
* field element (X9.62 section 4.3.3)
|
||||
*/
|
||||
SECItem b;
|
||||
SECItem seed;
|
||||
};
|
||||
typedef struct ECCurveStr ECCurve;
|
||||
|
||||
typedef void PRArenaPool;
|
||||
|
||||
struct ECParamsStr {
|
||||
PRArenaPool * arena;
|
||||
ECParamsType type;
|
||||
ECFieldID fieldID;
|
||||
ECCurve curve;
|
||||
SECItem base;
|
||||
SECItem order;
|
||||
int cofactor;
|
||||
SECItem DEREncoding;
|
||||
ECCurveName name;
|
||||
SECItem curveOID;
|
||||
};
|
||||
typedef struct ECParamsStr ECParams;
|
||||
|
||||
struct ECPublicKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* elliptic curve point encoded as
|
||||
* octet stream.
|
||||
*/
|
||||
};
|
||||
typedef struct ECPublicKeyStr ECPublicKey;
|
||||
|
||||
struct ECPrivateKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* encoded ec point */
|
||||
SECItem privateValue; /* private big integer */
|
||||
SECItem version; /* As per SEC 1, Appendix C, Section C.4 */
|
||||
};
|
||||
typedef struct ECPrivateKeyStr ECPrivateKey;
|
||||
|
||||
typedef enum _SECStatus {
|
||||
SECBufferTooSmall = -3,
|
||||
SECWouldBlock = -2,
|
||||
SECFailure = -1,
|
||||
SECSuccess = 0
|
||||
} SECStatus;
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define RNG_GenerateGlobalRandomBytes(p,l) ecc_knzero_random_generator((p), (l))
|
||||
#else
|
||||
/*
|
||||
This function is no longer required because the random bytes are now
|
||||
supplied by the caller. Force a failure.
|
||||
*/
|
||||
#define RNG_GenerateGlobalRandomBytes(p,l) SECFailure
|
||||
#endif
|
||||
#define CHECK_MPI_OK(func) if (MP_OKAY > (err = func)) goto cleanup
|
||||
#define MP_TO_SEC_ERROR(err)
|
||||
|
||||
#define SECITEM_TO_MPINT(it, mp) \
|
||||
CHECK_MPI_OK(mp_read_unsigned_octets((mp), (it).data, (it).len))
|
||||
|
||||
extern int ecc_knzero_random_generator(uint8_t *, size_t);
|
||||
extern ulong_t soft_nzero_random_generator(uint8_t *, ulong_t);
|
||||
|
||||
extern SECStatus EC_DecodeParams(const SECItem *, ECParams **, int);
|
||||
extern SECItem * SECITEM_AllocItem(PRArenaPool *, SECItem *, unsigned int, int);
|
||||
extern SECStatus SECITEM_CopyItem(PRArenaPool *, SECItem *, const SECItem *,
|
||||
int);
|
||||
extern void SECITEM_FreeItem(SECItem *, boolean_t);
|
||||
/* This function has been modified to accept an array of random bytes */
|
||||
extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
|
||||
const unsigned char* random, int randomlen, int);
|
||||
/* This function has been modified to accept an array of random bytes */
|
||||
extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *,
|
||||
const unsigned char* random, int randomlen, int, int timing);
|
||||
extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
|
||||
const SECItem *, int);
|
||||
extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
|
||||
SECItem *, int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ECC_IMPL_H */
|
@ -1,642 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
* Last Modified Date from the Original Code: Nov 2016
|
||||
*********************************************************************** */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#if !defined(__linux__) && !defined(_ALLBSD_SOURCE)
|
||||
#include <sys/systm.h>
|
||||
#endif /* __linux__ || _ALLBSD_SOURCE */
|
||||
#include <sys/param.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/kmem.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include "ec.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecc_impl.h"
|
||||
|
||||
#define MAX_ECKEY_LEN 72
|
||||
#define SEC_ASN1_OBJECT_ID 0x06
|
||||
|
||||
/*
|
||||
* Initializes a SECItem from a hexadecimal string
|
||||
*
|
||||
* Warning: This function ignores leading 00's, so any leading 00's
|
||||
* in the hexadecimal string must be optional.
|
||||
*/
|
||||
static SECItem *
|
||||
hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str,
|
||||
int kmflag)
|
||||
{
|
||||
int i = 0;
|
||||
int byteval = 0;
|
||||
int tmp = (int)strlen(str);
|
||||
|
||||
if ((tmp % 2) != 0) return NULL;
|
||||
|
||||
/* skip leading 00's unless the hex string is "00" */
|
||||
while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
|
||||
str += 2;
|
||||
tmp -= 2;
|
||||
}
|
||||
|
||||
item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2, kmflag);
|
||||
if (item->data == NULL) return NULL;
|
||||
item->len = tmp/2;
|
||||
|
||||
while (str[i]) {
|
||||
if ((str[i] >= '0') && (str[i] <= '9'))
|
||||
tmp = str[i] - '0';
|
||||
else if ((str[i] >= 'a') && (str[i] <= 'f'))
|
||||
tmp = str[i] - 'a' + 10;
|
||||
else if ((str[i] >= 'A') && (str[i] <= 'F'))
|
||||
tmp = str[i] - 'A' + 10;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
byteval = byteval * 16 + tmp;
|
||||
if ((i % 2) != 0) {
|
||||
item->data[i/2] = byteval;
|
||||
byteval = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params,
|
||||
int kmflag)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
const ECCurveParams *curveParams;
|
||||
/* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
|
||||
char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
|
||||
|
||||
if (((int)name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
|
||||
goto cleanup;
|
||||
params->name = name;
|
||||
curveParams = ecCurve_map[params->name];
|
||||
CHECK_OK(curveParams);
|
||||
if ((strlen(curveParams->genx) + strlen(curveParams->geny)) > 2 * 2 * MAX_ECKEY_LEN) {
|
||||
goto cleanup;
|
||||
}
|
||||
params->fieldID.size = curveParams->size;
|
||||
params->fieldID.type = field_type;
|
||||
if (field_type == ec_field_GFp) {
|
||||
CHECK_OK(hexString2SECItem(NULL, ¶ms->fieldID.u.prime,
|
||||
curveParams->irr, kmflag));
|
||||
} else {
|
||||
CHECK_OK(hexString2SECItem(NULL, ¶ms->fieldID.u.poly,
|
||||
curveParams->irr, kmflag));
|
||||
}
|
||||
CHECK_OK(hexString2SECItem(NULL, ¶ms->curve.a,
|
||||
curveParams->curvea, kmflag));
|
||||
CHECK_OK(hexString2SECItem(NULL, ¶ms->curve.b,
|
||||
curveParams->curveb, kmflag));
|
||||
genenc[0] = '0';
|
||||
genenc[1] = '4';
|
||||
genenc[2] = '\0';
|
||||
strcat(genenc, curveParams->genx);
|
||||
strcat(genenc, curveParams->geny);
|
||||
CHECK_OK(hexString2SECItem(NULL, ¶ms->base, genenc, kmflag));
|
||||
CHECK_OK(hexString2SECItem(NULL, ¶ms->order,
|
||||
curveParams->order, kmflag));
|
||||
params->cofactor = curveParams->cofactor;
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
cleanup:
|
||||
return rv;
|
||||
}
|
||||
|
||||
ECCurveName SECOID_FindOIDTag(const SECItem *);
|
||||
|
||||
SECStatus
|
||||
EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
|
||||
ECParams *params, int kmflag)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
ECCurveName tag;
|
||||
SECItem oid = { siBuffer, NULL, 0};
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
|
||||
printf("Encoded params in EC_DecodeParams: ");
|
||||
for (i = 0; i < encodedParams->len; i++) {
|
||||
printf("%02x:", encodedParams->data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
|
||||
(encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) &&
|
||||
(encodedParams->len != BRAINPOOL_CURVE_OID_TOTAL_LEN)) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
};
|
||||
|
||||
oid.len = encodedParams->len - 2;
|
||||
oid.data = encodedParams->data + 2;
|
||||
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
|
||||
((tag = SECOID_FindOIDTag(&oid)) == ECCurve_noName)) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
params->arena = arena;
|
||||
params->cofactor = 0;
|
||||
params->type = ec_params_named;
|
||||
params->name = ECCurve_noName;
|
||||
|
||||
/* For named curves, fill out curveOID */
|
||||
params->curveOID.len = oid.len;
|
||||
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(NULL, oid.len,
|
||||
kmflag);
|
||||
if (params->curveOID.data == NULL) goto cleanup;
|
||||
memcpy(params->curveOID.data, oid.data, oid.len);
|
||||
|
||||
#if EC_DEBUG
|
||||
#ifndef SECOID_FindOIDTagDescription
|
||||
printf("Curve: %s\n", ecCurve_map[tag]->text);
|
||||
#else
|
||||
printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
switch (tag) {
|
||||
|
||||
/* Binary curves */
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB163V1:
|
||||
/* Populate params for c2pnb163v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB163V2:
|
||||
/* Populate params for c2pnb163v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB163V3:
|
||||
/* Populate params for c2pnb163v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB176V1:
|
||||
/* Populate params for c2pnb176v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB191V1:
|
||||
/* Populate params for c2tnb191v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB191V2:
|
||||
/* Populate params for c2tnb191v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB191V3:
|
||||
/* Populate params for c2tnb191v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB208W1:
|
||||
/* Populate params for c2pnb208w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB239V1:
|
||||
/* Populate params for c2tnb239v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB239V2:
|
||||
/* Populate params for c2tnb239v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB239V3:
|
||||
/* Populate params for c2tnb239v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB272W1:
|
||||
/* Populate params for c2pnb272w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB304W1:
|
||||
/* Populate params for c2pnb304w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB359V1:
|
||||
/* Populate params for c2tnb359v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_PNB368W1:
|
||||
/* Populate params for c2pnb368w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_CHAR2_TNB431R1:
|
||||
/* Populate params for c2tnb431r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_113R1:
|
||||
/* Populate params for sect113r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_113R2:
|
||||
/* Populate params for sect113r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_131R1:
|
||||
/* Populate params for sect131r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_131R2:
|
||||
/* Populate params for sect131r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_163K1:
|
||||
/* Populate params for sect163k1
|
||||
* (the NIST K-163 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_163R1:
|
||||
/* Populate params for sect163r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_163R2:
|
||||
/* Populate params for sect163r2
|
||||
* (the NIST B-163 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_193R1:
|
||||
/* Populate params for sect193r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_193R2:
|
||||
/* Populate params for sect193r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_233K1:
|
||||
/* Populate params for sect233k1
|
||||
* (the NIST K-233 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_233R1:
|
||||
/* Populate params for sect233r1
|
||||
* (the NIST B-233 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_239K1:
|
||||
/* Populate params for sect239k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_283K1:
|
||||
/* Populate params for sect283k1
|
||||
* (the NIST K-283 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_283R1:
|
||||
/* Populate params for sect283r1
|
||||
* (the NIST B-283 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_409K1:
|
||||
/* Populate params for sect409k1
|
||||
* (the NIST K-409 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_409R1:
|
||||
/* Populate params for sect409r1
|
||||
* (the NIST B-409 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_571K1:
|
||||
/* Populate params for sect571k1
|
||||
* (the NIST K-571 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_CHAR2_571R1:
|
||||
/* Populate params for sect571r1
|
||||
* (the NIST B-571 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
/* Prime curves */
|
||||
|
||||
case ECCurve_X9_62_PRIME_192V1:
|
||||
/* Populate params for prime192v1 aka secp192r1
|
||||
* (the NIST P-192 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_PRIME_192V2:
|
||||
/* Populate params for prime192v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_PRIME_192V3:
|
||||
/* Populate params for prime192v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_PRIME_239V1:
|
||||
/* Populate params for prime239v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_PRIME_239V2:
|
||||
/* Populate params for prime239v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_PRIME_239V3:
|
||||
/* Populate params for prime239v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_X9_62_PRIME_256V1:
|
||||
/* Populate params for prime256v1 aka secp256r1
|
||||
* (the NIST P-256 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_112R1:
|
||||
/* Populate params for secp112r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_112R2:
|
||||
/* Populate params for secp112r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_128R1:
|
||||
/* Populate params for secp128r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_128R2:
|
||||
/* Populate params for secp128r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_160K1:
|
||||
/* Populate params for secp160k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_160R1:
|
||||
/* Populate params for secp160r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_160R2:
|
||||
/* Populate params for secp160r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_192K1:
|
||||
/* Populate params for secp192k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_224K1:
|
||||
/* Populate params for secp224k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_224R1:
|
||||
/* Populate params for secp224r1
|
||||
* (the NIST P-224 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_256K1:
|
||||
/* Populate params for secp256k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_384R1:
|
||||
/* Populate params for secp384r1
|
||||
* (the NIST P-384 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
/* Populate params for secp521r1
|
||||
* (the NIST P-521 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_BrainpoolP256r1:
|
||||
/* Populate params for brainpoolP256r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP256r1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_BrainpoolP320r1:
|
||||
/* Populate params for brainpoolP320r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP320r1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_BrainpoolP384r1:
|
||||
/* Populate params for brainpoolP384r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP384r1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
case ECCurve_BrainpoolP512r1:
|
||||
/* Populate params for brainpoolP512r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP512r1, ec_field_GFp,
|
||||
params, kmflag) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
cleanup:
|
||||
if (!params->cofactor) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
#if EC_DEBUG
|
||||
printf("Unrecognized curve, returning NULL params\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams, int kmflag)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
ECParams *params;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
/* Initialize an arena for the ECParams structure */
|
||||
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
|
||||
return SECFailure;
|
||||
|
||||
params = (ECParams *)PORT_ArenaZAlloc(NULL, sizeof(ECParams), kmflag);
|
||||
if (!params) {
|
||||
PORT_FreeArena(NULL, B_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Copy the encoded params */
|
||||
SECITEM_AllocItem(arena, &(params->DEREncoding), encodedParams->len,
|
||||
kmflag);
|
||||
memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
|
||||
|
||||
/* Fill out the rest of the ECParams structure based on
|
||||
* the encoded params
|
||||
*/
|
||||
rv = EC_FillParams(NULL, encodedParams, params, kmflag);
|
||||
if (rv == SECFailure) {
|
||||
PORT_FreeArena(NULL, B_TRUE);
|
||||
return SECFailure;
|
||||
} else {
|
||||
*ecparams = params;;
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
@ -1,733 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _ECL_CURVE_H
|
||||
#define _ECL_CURVE_H
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* NIST prime curves */
|
||||
static const ECCurveParams ecCurve_NIST_P192 = {
|
||||
"NIST-P192", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
||||
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
||||
"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P224 = {
|
||||
"NIST-P224", ECField_GFp, 224,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
||||
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
||||
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
||||
"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P256 = {
|
||||
"NIST-P256", ECField_GFp, 256,
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P384 = {
|
||||
"NIST-P384", ECField_GFp, 384,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||
1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P521 = {
|
||||
"NIST-P521", ECField_GFp, 521,
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||
1
|
||||
};
|
||||
|
||||
/* NIST binary curves */
|
||||
static const ECCurveParams ecCurve_NIST_K163 = {
|
||||
"NIST-K163", ECField_GF2m, 163,
|
||||
"0800000000000000000000000000000000000000C9",
|
||||
"000000000000000000000000000000000000000001",
|
||||
"000000000000000000000000000000000000000001",
|
||||
"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
|
||||
"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
|
||||
"04000000000000000000020108A2E0CC0D99F8A5EF", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_B163 = {
|
||||
"NIST-B163", ECField_GF2m, 163,
|
||||
"0800000000000000000000000000000000000000C9",
|
||||
"000000000000000000000000000000000000000001",
|
||||
"020A601907B8C953CA1481EB10512F78744A3205FD",
|
||||
"03F0EBA16286A2D57EA0991168D4994637E8343E36",
|
||||
"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
|
||||
"040000000000000000000292FE77E70C12A4234C33", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_K233 = {
|
||||
"NIST-K233", ECField_GF2m, 233,
|
||||
"020000000000000000000000000000000000000004000000000000000001",
|
||||
"000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000001",
|
||||
"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
|
||||
"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
|
||||
"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_B233 = {
|
||||
"NIST-B233", ECField_GF2m, 233,
|
||||
"020000000000000000000000000000000000000004000000000000000001",
|
||||
"000000000000000000000000000000000000000000000000000000000001",
|
||||
"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
|
||||
"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
|
||||
"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
|
||||
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_K283 = {
|
||||
"NIST-K283", ECField_GF2m, 283,
|
||||
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
|
||||
"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_B283 = {
|
||||
"NIST-B283", ECField_GF2m, 283,
|
||||
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
|
||||
"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
|
||||
"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
|
||||
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_K409 = {
|
||||
"NIST-K409", ECField_GF2m, 409,
|
||||
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
|
||||
"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
|
||||
"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_B409 = {
|
||||
"NIST-B409", ECField_GF2m, 409,
|
||||
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
|
||||
"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
|
||||
"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
|
||||
"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_K571 = {
|
||||
"NIST-K571", ECField_GF2m, 571,
|
||||
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
|
||||
"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
|
||||
"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_B571 = {
|
||||
"NIST-B571", ECField_GF2m, 571,
|
||||
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
|
||||
"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
|
||||
"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
|
||||
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", 2
|
||||
};
|
||||
|
||||
/* ANSI X9.62 prime curves */
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_192V2 = {
|
||||
"X9.62 P-192V2", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
|
||||
"EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
|
||||
"6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_192V3 = {
|
||||
"X9.62 P-192V3", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
|
||||
"7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
|
||||
"38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_239V1 = {
|
||||
"X9.62 P-239V1", ECField_GFp, 239,
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||
"6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
|
||||
"0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
|
||||
"7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_239V2 = {
|
||||
"X9.62 P-239V2", ECField_GFp, 239,
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||
"617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
|
||||
"38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
|
||||
"5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_239V3 = {
|
||||
"X9.62 P-239V3", ECField_GFp, 239,
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||
"255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
|
||||
"6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
|
||||
"1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", 1
|
||||
};
|
||||
|
||||
/* ANSI X9.62 binary curves */
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V1 = {
|
||||
"X9.62 C2-PNB163V1", ECField_GF2m, 163,
|
||||
"080000000000000000000000000000000000000107",
|
||||
"072546B5435234A422E0789675F432C89435DE5242",
|
||||
"00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9",
|
||||
"07AF69989546103D79329FCC3D74880F33BBE803CB",
|
||||
"01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F",
|
||||
"0400000000000000000001E60FC8821CC74DAEAFC1", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V2 = {
|
||||
"X9.62 C2-PNB163V2", ECField_GF2m, 163,
|
||||
"080000000000000000000000000000000000000107",
|
||||
"0108B39E77C4B108BED981ED0E890E117C511CF072",
|
||||
"0667ACEB38AF4E488C407433FFAE4F1C811638DF20",
|
||||
"0024266E4EB5106D0A964D92C4860E2671DB9B6CC5",
|
||||
"079F684DDF6684C5CD258B3890021B2386DFD19FC5",
|
||||
"03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V3 = {
|
||||
"X9.62 C2-PNB163V3", ECField_GF2m, 163,
|
||||
"080000000000000000000000000000000000000107",
|
||||
"07A526C63D3E25A256A007699F5447E32AE456B50E",
|
||||
"03F7061798EB99E238FD6F1BF95B48FEEB4854252B",
|
||||
"02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB",
|
||||
"05B935590C155E17EA48EB3FF3718B893DF59A05D0",
|
||||
"03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB176V1 = {
|
||||
"X9.62 C2-PNB176V1", ECField_GF2m, 176,
|
||||
"0100000000000000000000000000000000080000000007",
|
||||
"E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B",
|
||||
"5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2",
|
||||
"8D16C2866798B600F9F08BB4A8E860F3298CE04A5798",
|
||||
"6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C",
|
||||
"00010092537397ECA4F6145799D62B0A19CE06FE26AD", 0xFF6E
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V1 = {
|
||||
"X9.62 C2-TNB191V1", ECField_GF2m, 191,
|
||||
"800000000000000000000000000000000000000000000201",
|
||||
"2866537B676752636A68F56554E12640276B649EF7526267",
|
||||
"2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC",
|
||||
"36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D",
|
||||
"765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB",
|
||||
"40000000000000000000000004A20E90C39067C893BBB9A5", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V2 = {
|
||||
"X9.62 C2-TNB191V2", ECField_GF2m, 191,
|
||||
"800000000000000000000000000000000000000000000201",
|
||||
"401028774D7777C7B7666D1366EA432071274F89FF01E718",
|
||||
"0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01",
|
||||
"3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10",
|
||||
"17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A",
|
||||
"20000000000000000000000050508CB89F652824E06B8173", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V3 = {
|
||||
"X9.62 C2-TNB191V3", ECField_GF2m, 191,
|
||||
"800000000000000000000000000000000000000000000201",
|
||||
"6C01074756099122221056911C77D77E77A777E7E7E77FCB",
|
||||
"71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8",
|
||||
"375D4CE24FDE434489DE8746E71786015009E66E38A926DD",
|
||||
"545A39176196575D985999366E6AD34CE0A77CD7127B06BE",
|
||||
"155555555555555555555555610C0B196812BFB6288A3EA3", 6
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB208W1 = {
|
||||
"X9.62 C2-PNB208W1", ECField_GF2m, 208,
|
||||
"010000000000000000000000000000000800000000000000000007",
|
||||
"0000000000000000000000000000000000000000000000000000",
|
||||
"C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E",
|
||||
"89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A",
|
||||
"0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3",
|
||||
"000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 0xFE48
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V1 = {
|
||||
"X9.62 C2-TNB239V1", ECField_GF2m, 239,
|
||||
"800000000000000000000000000000000000000000000000001000000001",
|
||||
"32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
|
||||
"790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
|
||||
"57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D",
|
||||
"61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305",
|
||||
"2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V2 = {
|
||||
"X9.62 C2-TNB239V2", ECField_GF2m, 239,
|
||||
"800000000000000000000000000000000000000000000000001000000001",
|
||||
"4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F",
|
||||
"5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B",
|
||||
"28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205",
|
||||
"5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833",
|
||||
"1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 6
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V3 = {
|
||||
"X9.62 C2-TNB239V3", ECField_GF2m, 239,
|
||||
"800000000000000000000000000000000000000000000000001000000001",
|
||||
"01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F",
|
||||
"6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40",
|
||||
"70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92",
|
||||
"2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461",
|
||||
"0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 0xA
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB272W1 = {
|
||||
"X9.62 C2-PNB272W1", ECField_GF2m, 272,
|
||||
"010000000000000000000000000000000000000000000000000000010000000000000B",
|
||||
"91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20",
|
||||
"7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7",
|
||||
"6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D",
|
||||
"10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23",
|
||||
"000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521",
|
||||
0xFF06
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB304W1 = {
|
||||
"X9.62 C2-PNB304W1", ECField_GF2m, 304,
|
||||
"010000000000000000000000000000000000000000000000000000000000000000000000000807",
|
||||
"FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681",
|
||||
"BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE",
|
||||
"197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614",
|
||||
"E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B",
|
||||
"000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 0xFE2E
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB359V1 = {
|
||||
"X9.62 C2-TNB359V1", ECField_GF2m, 359,
|
||||
"800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001",
|
||||
"5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557",
|
||||
"2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988",
|
||||
"3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097",
|
||||
"53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD",
|
||||
"01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 0x4C
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB368W1 = {
|
||||
"X9.62 C2-PNB368W1", ECField_GF2m, 368,
|
||||
"0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007",
|
||||
"E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D",
|
||||
"FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A",
|
||||
"1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F",
|
||||
"7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310",
|
||||
"00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 0xFF70
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB431R1 = {
|
||||
"X9.62 C2-TNB431R1", ECField_GF2m, 431,
|
||||
"800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001",
|
||||
"1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F",
|
||||
"10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618",
|
||||
"120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7",
|
||||
"20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760",
|
||||
"0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 0x2760
|
||||
};
|
||||
|
||||
/* SEC2 prime curves */
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_112R1 = {
|
||||
"SECP-112R1", ECField_GFp, 112,
|
||||
"DB7C2ABF62E35E668076BEAD208B",
|
||||
"DB7C2ABF62E35E668076BEAD2088",
|
||||
"659EF8BA043916EEDE8911702B22",
|
||||
"09487239995A5EE76B55F9C2F098",
|
||||
"A89CE5AF8724C0A23E0E0FF77500",
|
||||
"DB7C2ABF62E35E7628DFAC6561C5", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_112R2 = {
|
||||
"SECP-112R2", ECField_GFp, 112,
|
||||
"DB7C2ABF62E35E668076BEAD208B",
|
||||
"6127C24C05F38A0AAAF65C0EF02C",
|
||||
"51DEF1815DB5ED74FCC34C85D709",
|
||||
"4BA30AB5E892B4E1649DD0928643",
|
||||
"adcd46f5882e3747def36e956e97",
|
||||
"36DF0AAFD8B8D7597CA10520D04B", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_128R1 = {
|
||||
"SECP-128R1", ECField_GFp, 128,
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"E87579C11079F43DD824993C2CEE5ED3",
|
||||
"161FF7528B899B2D0C28607CA52C5B86",
|
||||
"CF5AC8395BAFEB13C02DA292DDED7A83",
|
||||
"FFFFFFFE0000000075A30D1B9038A115", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_128R2 = {
|
||||
"SECP-128R2", ECField_GFp, 128,
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"D6031998D1B3BBFEBF59CC9BBFF9AEE1",
|
||||
"5EEEFCA380D02919DC2C6558BB6D8A5D",
|
||||
"7B6AA5D85E572983E6FB32A7CDEBC140",
|
||||
"27B6916A894D3AEE7106FE805FC34B44",
|
||||
"3FFFFFFF7FFFFFFFBE0024720613B5A3", 4
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_160K1 = {
|
||||
"SECP-160K1", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||
"0000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000007",
|
||||
"3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
|
||||
"938CF935318FDCED6BC28286531733C3F03C4FEE",
|
||||
"0100000000000000000001B8FA16DFAB9ACA16B6B3", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_160R1 = {
|
||||
"SECP-160R1", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
||||
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
||||
"4A96B5688EF573284664698968C38BB913CBFC82",
|
||||
"23A628553168947D59DCC912042351377AC5FB32",
|
||||
"0100000000000000000001F4C8F927AED3CA752257", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_160R2 = {
|
||||
"SECP-160R2", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
|
||||
"B4E134D3FB59EB8BAB57274904664D5AF50388BA",
|
||||
"52DCB034293A117E1F4FF11B30F7199D3144CE6D",
|
||||
"FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
|
||||
"0100000000000000000000351EE786A818F3A1A16B", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_192K1 = {
|
||||
"SECP-192K1", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000003",
|
||||
"DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
|
||||
"9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_224K1 = {
|
||||
"SECP-224K1", ECField_GFp, 224,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
|
||||
"00000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000005",
|
||||
"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
|
||||
"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
|
||||
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_256K1 = {
|
||||
"SECP-256K1", ECField_GFp, 256,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000007",
|
||||
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||
"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 1
|
||||
};
|
||||
|
||||
/* SEC2 binary curves */
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_113R1 = {
|
||||
"SECT-113R1", ECField_GF2m, 113,
|
||||
"020000000000000000000000000201",
|
||||
"003088250CA6E7C7FE649CE85820F7",
|
||||
"00E8BEE4D3E2260744188BE0E9C723",
|
||||
"009D73616F35F4AB1407D73562C10F",
|
||||
"00A52830277958EE84D1315ED31886",
|
||||
"0100000000000000D9CCEC8A39E56F", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_113R2 = {
|
||||
"SECT-113R2", ECField_GF2m, 113,
|
||||
"020000000000000000000000000201",
|
||||
"00689918DBEC7E5A0DD6DFC0AA55C7",
|
||||
"0095E9A9EC9B297BD4BF36E059184F",
|
||||
"01A57A6A7B26CA5EF52FCDB8164797",
|
||||
"00B3ADC94ED1FE674C06E695BABA1D",
|
||||
"010000000000000108789B2496AF93", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_131R1 = {
|
||||
"SECT-131R1", ECField_GF2m, 131,
|
||||
"080000000000000000000000000000010D",
|
||||
"07A11B09A76B562144418FF3FF8C2570B8",
|
||||
"0217C05610884B63B9C6C7291678F9D341",
|
||||
"0081BAF91FDF9833C40F9C181343638399",
|
||||
"078C6E7EA38C001F73C8134B1B4EF9E150",
|
||||
"0400000000000000023123953A9464B54D", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_131R2 = {
|
||||
"SECT-131R2", ECField_GF2m, 131,
|
||||
"080000000000000000000000000000010D",
|
||||
"03E5A88919D7CAFCBF415F07C2176573B2",
|
||||
"04B8266A46C55657AC734CE38F018F2192",
|
||||
"0356DCD8F2F95031AD652D23951BB366A8",
|
||||
"0648F06D867940A5366D9E265DE9EB240F",
|
||||
"0400000000000000016954A233049BA98F", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_163R1 = {
|
||||
"SECT-163R1", ECField_GF2m, 163,
|
||||
"0800000000000000000000000000000000000000C9",
|
||||
"07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
|
||||
"0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
|
||||
"0369979697AB43897789566789567F787A7876A654",
|
||||
"00435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
|
||||
"03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_193R1 = {
|
||||
"SECT-193R1", ECField_GF2m, 193,
|
||||
"02000000000000000000000000000000000000000000008001",
|
||||
"0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
|
||||
"00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
|
||||
"01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1",
|
||||
"0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
|
||||
"01000000000000000000000000C7F34A778F443ACC920EBA49", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_193R2 = {
|
||||
"SECT-193R2", ECField_GF2m, 193,
|
||||
"02000000000000000000000000000000000000000000008001",
|
||||
"0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
|
||||
"00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
|
||||
"00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F",
|
||||
"01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
|
||||
"010000000000000000000000015AAB561B005413CCD4EE99D5", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_239K1 = {
|
||||
"SECT-239K1", ECField_GF2m, 239,
|
||||
"800000000000000000004000000000000000000000000000000000000001",
|
||||
"000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000001",
|
||||
"29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC",
|
||||
"76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
|
||||
"2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", 4
|
||||
};
|
||||
|
||||
/* WTLS curves */
|
||||
static const ECCurveParams ecCurve_WTLS_1 = {
|
||||
"WTLS-1", ECField_GF2m, 113,
|
||||
"020000000000000000000000000201",
|
||||
"000000000000000000000000000001",
|
||||
"000000000000000000000000000001",
|
||||
"01667979A40BA497E5D5C270780617",
|
||||
"00F44B4AF1ECC2630E08785CEBCC15",
|
||||
"00FFFFFFFFFFFFFFFDBF91AF6DEA73", 2
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_WTLS_8 = {
|
||||
"WTLS-8", ECField_GFp, 112,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
|
||||
"0000000000000000000000000000",
|
||||
"0000000000000000000000000003",
|
||||
"0000000000000000000000000001",
|
||||
"0000000000000000000000000002",
|
||||
"0100000000000001ECEA551AD837E9", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_WTLS_9 = {
|
||||
"WTLS-9", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
|
||||
"0000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000003",
|
||||
"0000000000000000000000000000000000000001",
|
||||
"0000000000000000000000000000000000000002",
|
||||
"0100000000000000000001CDC98AE0E2DE574ABF33", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_BrainpoolP256r1 = {
|
||||
"brainpoolP256r1", ECField_GFp, 256,
|
||||
"A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
|
||||
"7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
|
||||
"26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
|
||||
"8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
|
||||
"547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
|
||||
"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_BrainpoolP320r1 = {
|
||||
"brainpoolP320r1", ECField_GFp, 320,
|
||||
"D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
|
||||
"3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
|
||||
"520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
|
||||
"43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
|
||||
"14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
|
||||
"D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_BrainpoolP384r1 = {
|
||||
"brainpoolP384r1", ECField_GFp, 384,
|
||||
"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
|
||||
"7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
|
||||
"04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
|
||||
"1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
|
||||
"8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
|
||||
"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_BrainpoolP512r1 = {
|
||||
"brainpoolP512r1", ECField_GFp, 512,
|
||||
"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
|
||||
"7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
|
||||
"3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
|
||||
"81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
|
||||
"7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
|
||||
"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 1
|
||||
};
|
||||
|
||||
/* mapping between ECCurveName enum and pointers to ECCurveParams */
|
||||
static const ECCurveParams *ecCurve_map[] = {
|
||||
NULL, /* ECCurve_noName */
|
||||
&ecCurve_NIST_P192, /* ECCurve_NIST_P192 */
|
||||
&ecCurve_NIST_P224, /* ECCurve_NIST_P224 */
|
||||
&ecCurve_NIST_P256, /* ECCurve_NIST_P256 */
|
||||
&ecCurve_NIST_P384, /* ECCurve_NIST_P384 */
|
||||
&ecCurve_NIST_P521, /* ECCurve_NIST_P521 */
|
||||
&ecCurve_NIST_K163, /* ECCurve_NIST_K163 */
|
||||
&ecCurve_NIST_B163, /* ECCurve_NIST_B163 */
|
||||
&ecCurve_NIST_K233, /* ECCurve_NIST_K233 */
|
||||
&ecCurve_NIST_B233, /* ECCurve_NIST_B233 */
|
||||
&ecCurve_NIST_K283, /* ECCurve_NIST_K283 */
|
||||
&ecCurve_NIST_B283, /* ECCurve_NIST_B283 */
|
||||
&ecCurve_NIST_K409, /* ECCurve_NIST_K409 */
|
||||
&ecCurve_NIST_B409, /* ECCurve_NIST_B409 */
|
||||
&ecCurve_NIST_K571, /* ECCurve_NIST_K571 */
|
||||
&ecCurve_NIST_B571, /* ECCurve_NIST_B571 */
|
||||
&ecCurve_X9_62_PRIME_192V2, /* ECCurve_X9_62_PRIME_192V2 */
|
||||
&ecCurve_X9_62_PRIME_192V3, /* ECCurve_X9_62_PRIME_192V3 */
|
||||
&ecCurve_X9_62_PRIME_239V1, /* ECCurve_X9_62_PRIME_239V1 */
|
||||
&ecCurve_X9_62_PRIME_239V2, /* ECCurve_X9_62_PRIME_239V2 */
|
||||
&ecCurve_X9_62_PRIME_239V3, /* ECCurve_X9_62_PRIME_239V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB163V1, /* ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
&ecCurve_X9_62_CHAR2_PNB163V2, /* ECCurve_X9_62_CHAR2_PNB163V2 */
|
||||
&ecCurve_X9_62_CHAR2_PNB163V3, /* ECCurve_X9_62_CHAR2_PNB163V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB176V1, /* ECCurve_X9_62_CHAR2_PNB176V1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB191V1, /* ECCurve_X9_62_CHAR2_TNB191V1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB191V2, /* ECCurve_X9_62_CHAR2_TNB191V2 */
|
||||
&ecCurve_X9_62_CHAR2_TNB191V3, /* ECCurve_X9_62_CHAR2_TNB191V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB208W1, /* ECCurve_X9_62_CHAR2_PNB208W1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB239V1, /* ECCurve_X9_62_CHAR2_TNB239V1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB239V2, /* ECCurve_X9_62_CHAR2_TNB239V2 */
|
||||
&ecCurve_X9_62_CHAR2_TNB239V3, /* ECCurve_X9_62_CHAR2_TNB239V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB272W1, /* ECCurve_X9_62_CHAR2_PNB272W1 */
|
||||
&ecCurve_X9_62_CHAR2_PNB304W1, /* ECCurve_X9_62_CHAR2_PNB304W1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB359V1, /* ECCurve_X9_62_CHAR2_TNB359V1 */
|
||||
&ecCurve_X9_62_CHAR2_PNB368W1, /* ECCurve_X9_62_CHAR2_PNB368W1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB431R1, /* ECCurve_X9_62_CHAR2_TNB431R1 */
|
||||
&ecCurve_SECG_PRIME_112R1, /* ECCurve_SECG_PRIME_112R1 */
|
||||
&ecCurve_SECG_PRIME_112R2, /* ECCurve_SECG_PRIME_112R2 */
|
||||
&ecCurve_SECG_PRIME_128R1, /* ECCurve_SECG_PRIME_128R1 */
|
||||
&ecCurve_SECG_PRIME_128R2, /* ECCurve_SECG_PRIME_128R2 */
|
||||
&ecCurve_SECG_PRIME_160K1, /* ECCurve_SECG_PRIME_160K1 */
|
||||
&ecCurve_SECG_PRIME_160R1, /* ECCurve_SECG_PRIME_160R1 */
|
||||
&ecCurve_SECG_PRIME_160R2, /* ECCurve_SECG_PRIME_160R2 */
|
||||
&ecCurve_SECG_PRIME_192K1, /* ECCurve_SECG_PRIME_192K1 */
|
||||
&ecCurve_SECG_PRIME_224K1, /* ECCurve_SECG_PRIME_224K1 */
|
||||
&ecCurve_SECG_PRIME_256K1, /* ECCurve_SECG_PRIME_256K1 */
|
||||
&ecCurve_SECG_CHAR2_113R1, /* ECCurve_SECG_CHAR2_113R1 */
|
||||
&ecCurve_SECG_CHAR2_113R2, /* ECCurve_SECG_CHAR2_113R2 */
|
||||
&ecCurve_SECG_CHAR2_131R1, /* ECCurve_SECG_CHAR2_131R1 */
|
||||
&ecCurve_SECG_CHAR2_131R2, /* ECCurve_SECG_CHAR2_131R2 */
|
||||
&ecCurve_SECG_CHAR2_163R1, /* ECCurve_SECG_CHAR2_163R1 */
|
||||
&ecCurve_SECG_CHAR2_193R1, /* ECCurve_SECG_CHAR2_193R1 */
|
||||
&ecCurve_SECG_CHAR2_193R2, /* ECCurve_SECG_CHAR2_193R2 */
|
||||
&ecCurve_SECG_CHAR2_239K1, /* ECCurve_SECG_CHAR2_239K1 */
|
||||
&ecCurve_WTLS_1, /* ECCurve_WTLS_1 */
|
||||
&ecCurve_WTLS_8, /* ECCurve_WTLS_8 */
|
||||
&ecCurve_WTLS_9, /* ECCurve_WTLS_9 */
|
||||
&ecCurve_BrainpoolP256r1, /* ECCurve_BrainpoolP256r1 */
|
||||
&ecCurve_BrainpoolP320r1, /* ECCurve_BrainpoolP320r1 */
|
||||
&ecCurve_BrainpoolP384r1, /* ECCurve_brainpoolP384r1 */
|
||||
&ecCurve_BrainpoolP512r1, /* ECCurve_brainpoolP512r1 */
|
||||
NULL /* ECCurve_pastLastCurve */
|
||||
};
|
||||
|
||||
#endif /* _ECL_CURVE_H */
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _ECL_EXP_H
|
||||
#define _ECL_EXP_H
|
||||
|
||||
/* Curve field type */
|
||||
typedef enum {
|
||||
ECField_GFp,
|
||||
ECField_GF2m
|
||||
} ECField;
|
||||
|
||||
/* Hexadecimal encoding of curve parameters */
|
||||
struct ECCurveParamsStr {
|
||||
char *text;
|
||||
ECField field;
|
||||
unsigned int size;
|
||||
char *irr;
|
||||
char *curvea;
|
||||
char *curveb;
|
||||
char *genx;
|
||||
char *geny;
|
||||
char *order;
|
||||
int cofactor;
|
||||
};
|
||||
typedef struct ECCurveParamsStr ECCurveParams;
|
||||
|
||||
/* Named curve parameters */
|
||||
typedef enum {
|
||||
|
||||
ECCurve_noName = 0,
|
||||
|
||||
/* NIST prime curves */
|
||||
ECCurve_NIST_P192,
|
||||
ECCurve_NIST_P224,
|
||||
ECCurve_NIST_P256,
|
||||
ECCurve_NIST_P384,
|
||||
ECCurve_NIST_P521,
|
||||
|
||||
/* NIST binary curves */
|
||||
ECCurve_NIST_K163,
|
||||
ECCurve_NIST_B163,
|
||||
ECCurve_NIST_K233,
|
||||
ECCurve_NIST_B233,
|
||||
ECCurve_NIST_K283,
|
||||
ECCurve_NIST_B283,
|
||||
ECCurve_NIST_K409,
|
||||
ECCurve_NIST_B409,
|
||||
ECCurve_NIST_K571,
|
||||
ECCurve_NIST_B571,
|
||||
|
||||
/* ANSI X9.62 prime curves */
|
||||
/* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */
|
||||
ECCurve_X9_62_PRIME_192V2,
|
||||
ECCurve_X9_62_PRIME_192V3,
|
||||
ECCurve_X9_62_PRIME_239V1,
|
||||
ECCurve_X9_62_PRIME_239V2,
|
||||
ECCurve_X9_62_PRIME_239V3,
|
||||
/* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */
|
||||
|
||||
/* ANSI X9.62 binary curves */
|
||||
ECCurve_X9_62_CHAR2_PNB163V1,
|
||||
ECCurve_X9_62_CHAR2_PNB163V2,
|
||||
ECCurve_X9_62_CHAR2_PNB163V3,
|
||||
ECCurve_X9_62_CHAR2_PNB176V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V2,
|
||||
ECCurve_X9_62_CHAR2_TNB191V3,
|
||||
ECCurve_X9_62_CHAR2_PNB208W1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V2,
|
||||
ECCurve_X9_62_CHAR2_TNB239V3,
|
||||
ECCurve_X9_62_CHAR2_PNB272W1,
|
||||
ECCurve_X9_62_CHAR2_PNB304W1,
|
||||
ECCurve_X9_62_CHAR2_TNB359V1,
|
||||
ECCurve_X9_62_CHAR2_PNB368W1,
|
||||
ECCurve_X9_62_CHAR2_TNB431R1,
|
||||
|
||||
/* SEC2 prime curves */
|
||||
ECCurve_SECG_PRIME_112R1,
|
||||
ECCurve_SECG_PRIME_112R2,
|
||||
ECCurve_SECG_PRIME_128R1,
|
||||
ECCurve_SECG_PRIME_128R2,
|
||||
ECCurve_SECG_PRIME_160K1,
|
||||
ECCurve_SECG_PRIME_160R1,
|
||||
ECCurve_SECG_PRIME_160R2,
|
||||
ECCurve_SECG_PRIME_192K1,
|
||||
/* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */
|
||||
ECCurve_SECG_PRIME_224K1,
|
||||
/* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */
|
||||
ECCurve_SECG_PRIME_256K1,
|
||||
/* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */
|
||||
/* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */
|
||||
/* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */
|
||||
|
||||
/* SEC2 binary curves */
|
||||
ECCurve_SECG_CHAR2_113R1,
|
||||
ECCurve_SECG_CHAR2_113R2,
|
||||
ECCurve_SECG_CHAR2_131R1,
|
||||
ECCurve_SECG_CHAR2_131R2,
|
||||
/* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */
|
||||
ECCurve_SECG_CHAR2_163R1,
|
||||
/* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */
|
||||
ECCurve_SECG_CHAR2_193R1,
|
||||
ECCurve_SECG_CHAR2_193R2,
|
||||
/* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */
|
||||
ECCurve_SECG_CHAR2_239K1,
|
||||
/* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */
|
||||
/* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */
|
||||
/* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */
|
||||
/* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */
|
||||
/* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */
|
||||
/* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */
|
||||
|
||||
/* WTLS curves */
|
||||
ECCurve_WTLS_1,
|
||||
/* there is no WTLS 2 curve */
|
||||
/* ECCurve_WTLS_3 == ECCurve_NIST_K163 */
|
||||
/* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */
|
||||
/* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
/* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */
|
||||
/* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */
|
||||
ECCurve_WTLS_8,
|
||||
ECCurve_WTLS_9,
|
||||
/* ECCurve_WTLS_10 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
|
||||
/* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
|
||||
|
||||
/* ECC Brainpool prime curves in RFC 5639*/
|
||||
ECCurve_BrainpoolP256r1,
|
||||
ECCurve_BrainpoolP320r1,
|
||||
ECCurve_BrainpoolP384r1,
|
||||
ECCurve_BrainpoolP512r1,
|
||||
|
||||
ECCurve_pastLastCurve
|
||||
} ECCurveName;
|
||||
|
||||
/* Aliased named curves */
|
||||
|
||||
#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192
|
||||
#define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192
|
||||
#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224
|
||||
#define ECCurve_SECG_PRIME_256R1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_384R1 ECCurve_NIST_P384
|
||||
#define ECCurve_SECG_PRIME_521R1 ECCurve_NIST_P521
|
||||
#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163
|
||||
#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163
|
||||
#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233
|
||||
#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233
|
||||
#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283
|
||||
#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283
|
||||
#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409
|
||||
#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409
|
||||
#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571
|
||||
#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571
|
||||
#define ECCurve_WTLS_3 ECCurve_NIST_K163
|
||||
#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1
|
||||
#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1
|
||||
#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1
|
||||
#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1
|
||||
#define ECCurve_WTLS_10 ECCurve_NIST_K233
|
||||
#define ECCurve_WTLS_11 ECCurve_NIST_B233
|
||||
#define ECCurve_WTLS_12 ECCurve_NIST_P224
|
||||
|
||||
#endif /* _ECL_EXP_H */
|
@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Stephen Fung <fungstep@hotmail.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _ECL_PRIV_H
|
||||
#define _ECL_PRIV_H
|
||||
|
||||
#include "ecl.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
|
||||
/* the following needs to go away... */
|
||||
#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
|
||||
#define ECL_SIXTY_FOUR_BIT
|
||||
#else
|
||||
#define ECL_THIRTY_TWO_BIT
|
||||
#endif
|
||||
|
||||
#define ECL_CURVE_DIGITS(curve_size_in_bits) \
|
||||
(((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8))
|
||||
#define ECL_BITS (sizeof(mp_digit)*8)
|
||||
#define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit))
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a. If i >= length(a),
|
||||
* then return 0. (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).) */
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(cin)) + (a1) + (a2); \
|
||||
s = ACCUM(w); \
|
||||
cout = CARRYOUT(w); }
|
||||
|
||||
/* Handle case when carry-in value is zero */
|
||||
#define MP_ADD_CARRY_ZERO(a1, a2, s, cout) \
|
||||
MP_ADD_CARRY(a1, a2, s, 0, cout);
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(a1)) - (a2) - (bin); \
|
||||
s = ACCUM(w); \
|
||||
bout = (w >> MP_DIGIT_BIT) & 1; }
|
||||
|
||||
#else
|
||||
/* NOTE,
|
||||
* cin and cout could be the same variable.
|
||||
* bin and bout could be the same variable.
|
||||
* a1 or a2 and s could be the same variable.
|
||||
* don't trash those outputs until their respective inputs have
|
||||
* been read. */
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_digit tmp,sum; \
|
||||
tmp = (a1); \
|
||||
sum = tmp + (a2); \
|
||||
tmp = (sum < tmp); /* detect overflow */ \
|
||||
s = sum += (cin); \
|
||||
cout = tmp + (sum < (cin)); }
|
||||
|
||||
/* Handle case when carry-in value is zero */
|
||||
#define MP_ADD_CARRY_ZERO(a1, a2, s, cout) \
|
||||
{ mp_digit tmp,sum; \
|
||||
tmp = (a1); \
|
||||
sum = tmp + (a2); \
|
||||
tmp = (sum < tmp); /* detect overflow */ \
|
||||
s = sum; \
|
||||
cout = tmp; }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_digit tmp; \
|
||||
tmp = (a1); \
|
||||
s = tmp - (a2); \
|
||||
tmp = (s > tmp); /* detect borrow */ \
|
||||
if ((bin) && !s--) tmp++; \
|
||||
bout = tmp; }
|
||||
#endif
|
||||
|
||||
|
||||
struct GFMethodStr;
|
||||
typedef struct GFMethodStr GFMethod;
|
||||
struct GFMethodStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Irreducible that defines the field. For prime fields, this is the
|
||||
* prime p. For binary polynomial fields, this is the bitstring
|
||||
* representation of the irreducible polynomial. */
|
||||
mp_int irr;
|
||||
/* For prime fields, the value irr_arr[0] is the number of bits in the
|
||||
* field. For binary polynomial fields, the irreducible polynomial
|
||||
* f(t) is represented as an array of unsigned int[], where f(t) is
|
||||
* of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0]
|
||||
* > p[1] > ... > p[4] = 0. */
|
||||
unsigned int irr_arr[5];
|
||||
/* Field arithmetic methods. All methods (except field_enc and
|
||||
* field_dec) are assumed to take field-encoded parameters and return
|
||||
* field-encoded values. All methods (except field_enc and field_dec)
|
||||
* are required to be implemented. */
|
||||
mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (GFMethod *meth);
|
||||
};
|
||||
|
||||
/* Construct generic GFMethods. */
|
||||
GFMethod *GFMethod_consGFp(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGFp_mont(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGF2m(const mp_int *irr,
|
||||
const unsigned int irr_arr[5]);
|
||||
/* Free the memory allocated (if any) to a GFMethod object. */
|
||||
void GFMethod_free(GFMethod *meth);
|
||||
|
||||
struct ECGroupStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Field definition and arithmetic. */
|
||||
GFMethod *meth;
|
||||
/* Textual representation of curve name, if any. */
|
||||
char *text;
|
||||
#ifdef _KERNEL
|
||||
int text_len;
|
||||
#endif
|
||||
/* Curve parameters, field-encoded. */
|
||||
mp_int curvea, curveb;
|
||||
/* x and y coordinates of the base point, field-encoded. */
|
||||
mp_int genx, geny;
|
||||
/* Order and cofactor of the base point. */
|
||||
mp_int order;
|
||||
int cofactor;
|
||||
/* Point arithmetic methods. All methods are assumed to take
|
||||
* field-encoded parameters and return field-encoded values. All
|
||||
* methods (except base_point_mul and points_mul) are required to be
|
||||
* implemented. */
|
||||
mp_err (*point_add) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_sub) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_mul) (const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group, int timing);
|
||||
mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group,
|
||||
int timing);
|
||||
mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (ECGroup *group);
|
||||
};
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* fixed length in-line adds. Count is in words */
|
||||
mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
/* Wrapper functions for generic binary polynomial field arithmetic. */
|
||||
mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* Montgomery prime field arithmetic. */
|
||||
mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
void ec_GFp_extra_free_mont(GFMethod *meth);
|
||||
|
||||
/* point multiplication */
|
||||
mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group,
|
||||
int timing);
|
||||
mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group,
|
||||
int timing);
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in,
|
||||
int w);
|
||||
|
||||
/* Optimized field arithmetic */
|
||||
mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp224(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp256(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp521(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gf2m163(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m193(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
|
||||
|
||||
/* Optimized floating-point arithmetic */
|
||||
#ifdef ECL_USE_FP
|
||||
mp_err ec_group_set_secp160r1_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp192_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp224_fp(ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* _ECL_PRIV_H */
|
@ -1,454 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ec2.h"
|
||||
#include "ecp.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* Allocate memory for a new ECGroup object. */
|
||||
ECGroup *
|
||||
ECGroup_new(int kmflag)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group;
|
||||
#ifdef _KERNEL
|
||||
group = (ECGroup *) kmem_alloc(sizeof(ECGroup), kmflag);
|
||||
#else
|
||||
group = (ECGroup *) malloc(sizeof(ECGroup));
|
||||
#endif
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
group->constructed = MP_YES;
|
||||
group->meth = NULL;
|
||||
group->text = NULL;
|
||||
MP_DIGITS(&group->curvea) = 0;
|
||||
MP_DIGITS(&group->curveb) = 0;
|
||||
MP_DIGITS(&group->genx) = 0;
|
||||
MP_DIGITS(&group->geny) = 0;
|
||||
MP_DIGITS(&group->order) = 0;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = NULL;
|
||||
group->validate_point = NULL;
|
||||
group->extra1 = NULL;
|
||||
group->extra2 = NULL;
|
||||
group->extra_free = NULL;
|
||||
MP_CHECKOK(mp_init(&group->curvea, kmflag));
|
||||
MP_CHECKOK(mp_init(&group->curveb, kmflag));
|
||||
MP_CHECKOK(mp_init(&group->genx, kmflag));
|
||||
MP_CHECKOK(mp_init(&group->geny, kmflag));
|
||||
MP_CHECKOK(mp_init(&group->order, kmflag));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new(FLAG(irr));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields with
|
||||
* field arithmetic implemented in Montgomery coordinates. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new(FLAG(irr));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp_mont(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curvea, &group->curvea, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curveb, &group->curveb, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
/* Construct a generic ECGroup for elliptic curves over binary polynomial
|
||||
* fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],
|
||||
const mp_int *curvea, const mp_int *curveb,
|
||||
const mp_int *genx, const mp_int *geny,
|
||||
const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new(FLAG(irr));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGF2m(irr, irr_arr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GF2m_pt_add_aff;
|
||||
group->point_sub = &ec_GF2m_pt_sub_aff;
|
||||
group->point_dbl = &ec_GF2m_pt_dbl_aff;
|
||||
group->point_mul = &ec_GF2m_pt_mul_mont;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->validate_point = &ec_GF2m_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Construct ECGroup from hex parameters and name, if any. Called by
|
||||
* ECGroup_fromHex and ECGroup_fromName. */
|
||||
ECGroup *
|
||||
ecgroup_fromNameAndHex(const ECCurveName name,
|
||||
const ECCurveParams * params, int kmflag)
|
||||
{
|
||||
mp_int irr, curvea, curveb, genx, geny, order;
|
||||
int bits;
|
||||
ECGroup *group = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* initialize values */
|
||||
MP_DIGITS(&irr) = 0;
|
||||
MP_DIGITS(&curvea) = 0;
|
||||
MP_DIGITS(&curveb) = 0;
|
||||
MP_DIGITS(&genx) = 0;
|
||||
MP_DIGITS(&geny) = 0;
|
||||
MP_DIGITS(&order) = 0;
|
||||
MP_CHECKOK(mp_init(&irr, kmflag));
|
||||
MP_CHECKOK(mp_init(&curvea, kmflag));
|
||||
MP_CHECKOK(mp_init(&curveb, kmflag));
|
||||
MP_CHECKOK(mp_init(&genx, kmflag));
|
||||
MP_CHECKOK(mp_init(&geny, kmflag));
|
||||
MP_CHECKOK(mp_init(&order, kmflag));
|
||||
MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
|
||||
MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
|
||||
MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
|
||||
MP_CHECKOK(mp_read_radix(&order, params->order, 16));
|
||||
|
||||
/* determine number of bits */
|
||||
bits = mpl_significant_bits(&irr) - 1;
|
||||
if (bits < MP_OKAY) {
|
||||
res = bits;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* determine which optimizations (if any) to use */
|
||||
if (params->field == ECField_GFp) {
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
switch (name) {
|
||||
#ifdef ECL_USE_FP
|
||||
case ECCurve_SECG_PRIME_160R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_secp160r1_fp(group));
|
||||
break;
|
||||
#endif
|
||||
case ECCurve_SECG_PRIME_192R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp192_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp192(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_224R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp224_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp224(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_256R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp256(group, name));
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp521(group, name));
|
||||
break;
|
||||
default:
|
||||
/* use generic arithmetic */
|
||||
#endif
|
||||
group =
|
||||
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
}
|
||||
} else if (params->field == ECField_GF2m) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
if ((name == ECCurve_NIST_K163) ||
|
||||
(name == ECCurve_NIST_B163) ||
|
||||
(name == ECCurve_SECG_CHAR2_163R1)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m163(group, name));
|
||||
} else if ((name == ECCurve_SECG_CHAR2_193R1) ||
|
||||
(name == ECCurve_SECG_CHAR2_193R2)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m193(group, name));
|
||||
} else if ((name == ECCurve_NIST_K233) ||
|
||||
(name == ECCurve_NIST_B233)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m233(group, name));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* set name, if any */
|
||||
if ((group != NULL) && (params->text != NULL)) {
|
||||
#ifdef _KERNEL
|
||||
int n = strlen(params->text) + 1;
|
||||
|
||||
group->text = kmem_alloc(n, kmflag);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
bcopy(params->text, group->text, n);
|
||||
group->text_len = n;
|
||||
#else
|
||||
group->text = strdup(params->text);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&irr);
|
||||
mp_clear(&curvea);
|
||||
mp_clear(&curveb);
|
||||
mp_clear(&genx);
|
||||
mp_clear(&geny);
|
||||
mp_clear(&order);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromHex(const ECCurveParams * params, int kmflag)
|
||||
{
|
||||
return ecgroup_fromNameAndHex(ECCurve_noName, params, kmflag);
|
||||
}
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromName(const ECCurveName name, int kmflag)
|
||||
{
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
params = EC_GetNamedCurveParams(name, kmflag);
|
||||
if (params == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* construct actual group */
|
||||
group = ecgroup_fromNameAndHex(name, params, kmflag);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py)
|
||||
{
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
return group->validate_point(px, py, group);
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECGroup object. */
|
||||
void
|
||||
ECGroup_free(ECGroup *group)
|
||||
{
|
||||
if (group == NULL)
|
||||
return;
|
||||
GFMethod_free(group->meth);
|
||||
if (group->constructed == MP_NO)
|
||||
return;
|
||||
mp_clear(&group->curvea);
|
||||
mp_clear(&group->curveb);
|
||||
mp_clear(&group->genx);
|
||||
mp_clear(&group->geny);
|
||||
mp_clear(&group->order);
|
||||
if (group->text != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(group->text, group->text_len);
|
||||
#else
|
||||
free(group->text);
|
||||
#endif
|
||||
if (group->extra_free != NULL)
|
||||
group->extra_free(group);
|
||||
#ifdef _KERNEL
|
||||
kmem_free(group, sizeof (ECGroup));
|
||||
#else
|
||||
free(group);
|
||||
#endif
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _ECL_H
|
||||
#define _ECL_H
|
||||
|
||||
/* Although this is not an exported header file, code which uses elliptic
|
||||
* curve point operations will need to include it. */
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include "mpi.h"
|
||||
|
||||
struct ECGroupStr;
|
||||
typedef struct ECGroupStr ECGroup;
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *ECGroup_fromHex(const ECCurveParams * params, int kmflag);
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *ECGroup_fromName(const ECCurveName name, int kmflag);
|
||||
|
||||
/* Free an allocated ECGroup. */
|
||||
void ECGroup_free(ECGroup *group);
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name, int kmflag);
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *ECCurveParams_dup(const ECCurveParams * params, int kmflag);
|
||||
|
||||
/* Free an allocated ECCurveParams */
|
||||
void EC_FreeCurveParams(ECCurveParams * params);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *qx, mp_int *qy,
|
||||
int timing);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Input and output values are assumed to
|
||||
* be NOT field-encoded. */
|
||||
mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
|
||||
const mp_int *k2, const mp_int *px, const mp_int *py,
|
||||
mp_int *qx, mp_int *qy, int timing);
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62.
|
||||
* Returns MP_YES if the public key is valid, MP_NO if the public key
|
||||
* is invalid, or an error code if the validation could not be
|
||||
* performed. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py);
|
||||
|
||||
#endif /* _ECL_H */
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecl-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; }
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *
|
||||
ECCurveParams_dup(const ECCurveParams * params, int kmflag)
|
||||
{
|
||||
int res = 1;
|
||||
ECCurveParams *ret = NULL;
|
||||
|
||||
#ifdef _KERNEL
|
||||
ret = (ECCurveParams *) kmem_zalloc(sizeof(ECCurveParams), kmflag);
|
||||
#else
|
||||
CHECK(ret = (ECCurveParams *) calloc(1, sizeof(ECCurveParams)));
|
||||
#endif
|
||||
if (params->text != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->text = kmem_alloc(strlen(params->text) + 1, kmflag);
|
||||
bcopy(params->text, ret->text, strlen(params->text) + 1);
|
||||
#else
|
||||
CHECK(ret->text = strdup(params->text));
|
||||
#endif
|
||||
}
|
||||
ret->field = params->field;
|
||||
ret->size = params->size;
|
||||
if (params->irr != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->irr = kmem_alloc(strlen(params->irr) + 1, kmflag);
|
||||
bcopy(params->irr, ret->irr, strlen(params->irr) + 1);
|
||||
#else
|
||||
CHECK(ret->irr = strdup(params->irr));
|
||||
#endif
|
||||
}
|
||||
if (params->curvea != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->curvea = kmem_alloc(strlen(params->curvea) + 1, kmflag);
|
||||
bcopy(params->curvea, ret->curvea, strlen(params->curvea) + 1);
|
||||
#else
|
||||
CHECK(ret->curvea = strdup(params->curvea));
|
||||
#endif
|
||||
}
|
||||
if (params->curveb != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->curveb = kmem_alloc(strlen(params->curveb) + 1, kmflag);
|
||||
bcopy(params->curveb, ret->curveb, strlen(params->curveb) + 1);
|
||||
#else
|
||||
CHECK(ret->curveb = strdup(params->curveb));
|
||||
#endif
|
||||
}
|
||||
if (params->genx != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->genx = kmem_alloc(strlen(params->genx) + 1, kmflag);
|
||||
bcopy(params->genx, ret->genx, strlen(params->genx) + 1);
|
||||
#else
|
||||
CHECK(ret->genx = strdup(params->genx));
|
||||
#endif
|
||||
}
|
||||
if (params->geny != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->geny = kmem_alloc(strlen(params->geny) + 1, kmflag);
|
||||
bcopy(params->geny, ret->geny, strlen(params->geny) + 1);
|
||||
#else
|
||||
CHECK(ret->geny = strdup(params->geny));
|
||||
#endif
|
||||
}
|
||||
if (params->order != NULL) {
|
||||
#ifdef _KERNEL
|
||||
ret->order = kmem_alloc(strlen(params->order) + 1, kmflag);
|
||||
bcopy(params->order, ret->order, strlen(params->order) + 1);
|
||||
#else
|
||||
CHECK(ret->order = strdup(params->order));
|
||||
#endif
|
||||
}
|
||||
ret->cofactor = params->cofactor;
|
||||
|
||||
CLEANUP:
|
||||
if (res != 1) {
|
||||
EC_FreeCurveParams(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *
|
||||
EC_GetNamedCurveParams(const ECCurveName name, int kmflag)
|
||||
{
|
||||
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
|
||||
(ecCurve_map[name] == NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ECCurveParams_dup(ecCurve_map[name], kmflag);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECCurveParams object. */
|
||||
void
|
||||
EC_FreeCurveParams(ECCurveParams * params)
|
||||
{
|
||||
if (params == NULL)
|
||||
return;
|
||||
if (params->text != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->text, strlen(params->text) + 1);
|
||||
#else
|
||||
free(params->text);
|
||||
#endif
|
||||
if (params->irr != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->irr, strlen(params->irr) + 1);
|
||||
#else
|
||||
free(params->irr);
|
||||
#endif
|
||||
if (params->curvea != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->curvea, strlen(params->curvea) + 1);
|
||||
#else
|
||||
free(params->curvea);
|
||||
#endif
|
||||
if (params->curveb != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->curveb, strlen(params->curveb) + 1);
|
||||
#else
|
||||
free(params->curveb);
|
||||
#endif
|
||||
if (params->genx != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->genx, strlen(params->genx) + 1);
|
||||
#else
|
||||
free(params->genx);
|
||||
#endif
|
||||
if (params->geny != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->geny, strlen(params->geny) + 1);
|
||||
#else
|
||||
free(params->geny);
|
||||
#endif
|
||||
if (params->order != NULL)
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params->order, strlen(params->order) + 1);
|
||||
#else
|
||||
free(params->order);
|
||||
#endif
|
||||
#ifdef _KERNEL
|
||||
kmem_free(params, sizeof(ECCurveParams));
|
||||
#else
|
||||
free(params);
|
||||
#endif
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,362 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int kt;
|
||||
|
||||
ARGCHK((k != NULL) && (group != NULL), MP_BADARG);
|
||||
MP_DIGITS(&kt) = 0;
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (mp_cmp(k, &group->order) > 0) {
|
||||
MP_CHECKOK(mp_init(&kt, FLAG(k)));
|
||||
MP_CHECKOK(mp_mod(k, &group->order, &kt));
|
||||
} else {
|
||||
MP_SIGN(&kt) = MP_ZPOS;
|
||||
MP_USED(&kt) = MP_USED(k);
|
||||
MP_ALLOC(&kt) = MP_ALLOC(k);
|
||||
MP_DIGITS(&kt) = MP_DIGITS(k);
|
||||
}
|
||||
|
||||
if ((px == NULL) || (py == NULL)) {
|
||||
if (group->base_point_mul) {
|
||||
MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group));
|
||||
} else {
|
||||
kt.flag = (mp_sign)0;
|
||||
MP_CHECKOK(group->
|
||||
point_mul(&kt, &group->genx, &group->geny, rx, ry,
|
||||
group, timing));
|
||||
}
|
||||
} else {
|
||||
kt.flag = (mp_sign)0;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(py, ry, group->meth));
|
||||
MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group, timing));
|
||||
} else {
|
||||
MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group, timing));
|
||||
}
|
||||
}
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if (MP_DIGITS(&kt) != MP_DIGITS(k)) {
|
||||
mp_clear(&kt);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group, int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry, timing);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing);
|
||||
}
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&sx, FLAG(k1)));
|
||||
MP_CHECKOK(mp_init(&sy, FLAG(k1)));
|
||||
|
||||
MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy, timing));
|
||||
MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry, timing));
|
||||
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. Uses
|
||||
* algorithm 15 (simultaneous multiple point multiplication) from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST
|
||||
* Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group, int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry, timing);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][0],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS, FLAG(k1)) );
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][1],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS, FLAG(k1)) );
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(group->
|
||||
point_add(rx, ry, &precomp[ai][bi][0],
|
||||
&precomp[ai][bi][1], rx, ry, group));
|
||||
}
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k1t, k2t;
|
||||
const mp_int *k1p, *k2p;
|
||||
|
||||
MP_DIGITS(&k1t) = 0;
|
||||
MP_DIGITS(&k2t) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (k1 != NULL) {
|
||||
if (mp_cmp(k1, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k1t, FLAG(k1)));
|
||||
MP_CHECKOK(mp_mod(k1, &group->order, &k1t));
|
||||
k1p = &k1t;
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
if (k2 != NULL) {
|
||||
if (mp_cmp(k2, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k2t, FLAG(k2)));
|
||||
MP_CHECKOK(mp_mod(k2, &group->order, &k2t));
|
||||
k2p = &k2t;
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
|
||||
/* if points_mul is defined, then use it */
|
||||
if (group->points_mul) {
|
||||
res = group->points_mul(k1p, k2p, px, py, rx, ry, group, timing);
|
||||
} else {
|
||||
res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group, timing);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k1t);
|
||||
mp_clear(&k2t);
|
||||
return res;
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _ECP_H
|
||||
#define _ECP_H
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). */
|
||||
mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R(x, y) = k1 * G + k2 * P(x, y), where G is the generator
|
||||
* (base point) of the group of points on the elliptic curve. Allows k1 =
|
||||
* NULL or { k2, P } = NULL. Implemented using mixed Jacobian-affine
|
||||
* coordinates. Input and output values are assumed to be NOT
|
||||
* field-encoded and are in affine form. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group, int timing);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. The implementation includes a countermeasure
|
||||
* that attempts to hide the size of n from timing channels. This counter-
|
||||
* measure is enabled using the timing argument. The high-rder bits of timing
|
||||
* must be uniformly random in order for this countermeasure to work. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group,
|
||||
int timing);
|
||||
|
||||
#endif /* _ECP_H */
|
@ -1,517 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define ECP192_DIGITS ECL_CURVE_DIGITS(192)
|
||||
|
||||
/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
mp_digit r3;
|
||||
#ifndef MPI_AMD64_ADD
|
||||
mp_digit carry;
|
||||
#endif
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b;
|
||||
#else
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0;
|
||||
mp_digit r0, r1, r2;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP192_DIGITS) {
|
||||
if (a == r) {
|
||||
return MP_OKAY;
|
||||
}
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECP192_DIGITS*2) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
/* copy out upper words of a */
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
|
||||
/* in all the math below,
|
||||
* nXb is most signifiant, nXa is least significant */
|
||||
switch (a_used) {
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a3a = MP_DIGIT(a, 6);
|
||||
}
|
||||
|
||||
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
MP_ADD_CARRY(r0a, a3a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a3b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a3a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a3b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a4b, r2b, carry, carry);
|
||||
r3 = carry; carry = 0;
|
||||
MP_ADD_CARRY(r0a, a5a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a5b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a5a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a5b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a5a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a5b, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1a, a4a, r1a, 0, carry);
|
||||
MP_ADD_CARRY(r1b, a4b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
MP_ADD_CARRY(r0a, r3, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, r3, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, 0, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 = carry;
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (((r2b == 0xffffffff) && (r2a == 0xffffffff)
|
||||
&& (r1b == 0xffffffff) ) &&
|
||||
((r1a == 0xffffffff) ||
|
||||
(r1a == 0xfffffffe) && (r0a == 0xffffffff) &&
|
||||
(r0b == 0xffffffff)) ) {
|
||||
/* do a quick subtract */
|
||||
MP_ADD_CARRY(r0a, 1, r0a, 0, carry);
|
||||
r0b += carry;
|
||||
r1a = r1b = r2a = r2b = 0;
|
||||
}
|
||||
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
}
|
||||
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY_ZERO(r0, a3, r0, carry);
|
||||
MP_ADD_CARRY(r1, a3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a4, r2, carry, carry);
|
||||
r3 = carry;
|
||||
MP_ADD_CARRY_ZERO(r0, a5, r0, carry);
|
||||
MP_ADD_CARRY(r1, a5, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a5, r2, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY_ZERO(r1, a4, r1, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
#else
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* set the lower words of r */
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq %5,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %6,%0 \n\t"
|
||||
"adcq %6,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %5,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3),
|
||||
"=r"(a4), "=r"(a5)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3),
|
||||
"4" (a3), "5" (a4), "6"(a5)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY_ZERO(r0, r3, r0, carry);
|
||||
MP_ADD_CARRY(r1, r3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 = carry;
|
||||
#else
|
||||
a3=r3;
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (r3 || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
/* do a quick subtract */
|
||||
r0++;
|
||||
r1 = r2 = 0;
|
||||
}
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
}
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_USED(r) = 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
/* Compute the sum of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a0 = 0, a1 = 0, a2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit carry;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
a0 = MP_DIGIT(a,0);
|
||||
}
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY_ZERO(a0, r0, r0, carry);
|
||||
MP_ADD_CARRY(a1, r1, r1, carry, carry);
|
||||
MP_ADD_CARRY(a2, r2, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %5,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
|
||||
: "r" (a0), "r" (a1), "r" (a2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'subract' if we've gone over
|
||||
* (add the 2's complement of the curve field) */
|
||||
if (carry || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY_ZERO(r0, 1, r0, carry);
|
||||
MP_ADD_CARRY(r1, 1, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"addq $1,%0 \n\t"
|
||||
"adcq $1,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the diff of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit b0 = 0, b1 = 0, b2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit borrow;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(a,0);
|
||||
}
|
||||
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
b0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, b0, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"subq %4,%0 \n\t"
|
||||
"sbbq %5,%1 \n\t"
|
||||
"sbbq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow)
|
||||
: "r" (b0), "r" (b1), "r" (b2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'add' if we've gone under 0
|
||||
* (subtract the 2's complement of the curve field) */
|
||||
if (borrow) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, 1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, 0, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"subq $1,%0 \n\t"
|
||||
"sbbq $1,%1 \n\t"
|
||||
"sbbq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p192. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p192.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p192. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t, FLAG(b)));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp192(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P192) {
|
||||
group->meth->field_mod = &ec_GFp_nistp192_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp192_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp192_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp192_div;
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
group->meth->field_add = &ec_GFp_nistp192_add;
|
||||
group->meth->field_sub = &ec_GFp_nistp192_sub;
|
||||
#endif
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,373 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define ECP224_DIGITS ECL_CURVE_DIGITS(224)
|
||||
|
||||
/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
|
||||
int r3b;
|
||||
mp_digit carry;
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6a = 0, a6b = 0,
|
||||
a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
|
||||
#else
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
|
||||
mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP224_DIGITS) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECL_CURVE_DIGITS(224*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 14:
|
||||
a6b = MP_DIGIT(a, 13);
|
||||
case 13:
|
||||
a6a = MP_DIGIT(a, 12);
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
}
|
||||
r3a = MP_DIGIT(a, 6);
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1b, a3b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
|
||||
r3b = carry;
|
||||
MP_ADD_CARRY (r1b, a5b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, 0, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
MP_SUB_BORROW(r0a, a3b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
MP_SUB_BORROW(r0a, a5b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
}
|
||||
|
||||
while (r3b > 0) {
|
||||
int tmp;
|
||||
MP_ADD_CARRY(r1b, r3b, r1b, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
MP_ADD_CARRY(r3a, 0, r3a, carry, carry);
|
||||
}
|
||||
tmp = carry;
|
||||
MP_SUB_BORROW(r0a, r3b, r0a, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
tmp -= carry;
|
||||
}
|
||||
r3b = tmp;
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
mp_digit maxInt = MP_DIGIT_MAX;
|
||||
MP_ADD_CARRY (r0a, 1, r0a, 0, carry);
|
||||
MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
|
||||
MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
|
||||
MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
|
||||
&& (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
|
||||
((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0a, 1, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
r1b = r2a = r2b = r3a = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 7;
|
||||
MP_DIGIT(r, 6) = r3a;
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
#else
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
a6b = a6 >> 32;
|
||||
a6a_a5b = a6 << 32;
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
a5b = a5 >> 32;
|
||||
a6a_a5b |= a5b;
|
||||
a5b = a5b << 32;
|
||||
a5a_a4b = a5 << 32;
|
||||
a5a = a5 & 0xffffffff;
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
a5a_a4b |= a4 >> 32;
|
||||
a4a_a3b = a4 << 32;
|
||||
case 4:
|
||||
a3b = MP_DIGIT(a, 3) >> 32;
|
||||
a4a_a3b |= a3b;
|
||||
a3b = a3b << 32;
|
||||
}
|
||||
|
||||
r3 = MP_DIGIT(a, 3) & 0xffffffff;
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY_ZERO (r1, a3b, r1, carry);
|
||||
MP_ADD_CARRY (r2, a4 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, a5a, r3, carry, carry);
|
||||
MP_ADD_CARRY_ZERO (r1, a5b, r1, carry);
|
||||
MP_ADD_CARRY (r2, a6 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, 0, r3, carry, carry);
|
||||
|
||||
MP_SUB_BORROW(r0, a4a_a3b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6b , r3, carry, carry);
|
||||
MP_SUB_BORROW(r0, a6a_a5b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6b , r1, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
|
||||
|
||||
/* if the value is negative, r3 has a 2's complement
|
||||
* high value */
|
||||
r3b = (int)(r3 >>32);
|
||||
while (r3b > 0) {
|
||||
r3 &= 0xffffffff;
|
||||
MP_ADD_CARRY_ZERO(r1,((mp_digit)r3b) << 32, r1, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, 0, r3, carry, carry);
|
||||
}
|
||||
MP_SUB_BORROW(r0, r3b, r0, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
MP_ADD_CARRY_ZERO (r0, 1, r0, carry);
|
||||
MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
|
||||
MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
|
||||
&& ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
|
||||
((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
r2 = r3 = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 4));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
MP_DIGIT(r, 3) = r3;
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p224. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p224.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p224.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p224. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t, FLAG(b)));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp224(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P224) {
|
||||
group->meth->field_mod = &ec_GFp_nistp224_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp224_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp224_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp224_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,430 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r.
|
||||
* Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
mp_digit carry;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a8=0, a9=0, a10=0, a11=0, a12=0, a13=0, a14=0, a15=0;
|
||||
mp_digit r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
int r8; /* must be a signed value ! */
|
||||
#else
|
||||
mp_digit a4=0, a5=0, a6=0, a7=0;
|
||||
mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
int r4; /* must be a signed value ! */
|
||||
#endif
|
||||
/* for polynomials larger than twice the field size
|
||||
* use regular reduction */
|
||||
if (a_bits < 256) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a,r);
|
||||
}
|
||||
if (a_bits > 512) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
switch (a_used) {
|
||||
case 16:
|
||||
a15 = MP_DIGIT(a,15);
|
||||
case 15:
|
||||
a14 = MP_DIGIT(a,14);
|
||||
case 14:
|
||||
a13 = MP_DIGIT(a,13);
|
||||
case 13:
|
||||
a12 = MP_DIGIT(a,12);
|
||||
case 12:
|
||||
a11 = MP_DIGIT(a,11);
|
||||
case 11:
|
||||
a10 = MP_DIGIT(a,10);
|
||||
case 10:
|
||||
a9 = MP_DIGIT(a,9);
|
||||
case 9:
|
||||
a8 = MP_DIGIT(a,8);
|
||||
}
|
||||
|
||||
r0 = MP_DIGIT(a,0);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r4 = MP_DIGIT(a,4);
|
||||
r5 = MP_DIGIT(a,5);
|
||||
r6 = MP_DIGIT(a,6);
|
||||
r7 = MP_DIGIT(a,7);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 = carry;
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r3, a12, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* combine last bottom of sum 3 with second sum 2 */
|
||||
MP_ADD_CARRY(r0, a8, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a9, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a10, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a12, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry); /* from sum 3 */
|
||||
r8 += carry;
|
||||
/* sum 3 (rest of it)*/
|
||||
MP_ADD_CARRY(r6, a14, r6, 0, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 4 (rest of it)*/
|
||||
MP_ADD_CARRY(r0, a9, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a10, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a11, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a13, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a14, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a15, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a13, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a8, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a11, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a12, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a13, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a8, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a10, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a12, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a13, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a14, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a15, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a9, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a11, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a13, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a14, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a15, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a8, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a9, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a10, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a12, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a14, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a15, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a9, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a10, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a11, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a13, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r8 > 0) {
|
||||
mp_digit r8_d = r8;
|
||||
MP_ADD_CARRY(r0, r8_d, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 0, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, -r8_d, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r8 < 0) {
|
||||
mp_digit r8_d = -r8;
|
||||
MP_SUB_BORROW(r0, r8_d, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, -r8_d, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = -carry;
|
||||
}
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,8));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 8;
|
||||
|
||||
MP_DIGIT(r,7) = r7;
|
||||
MP_DIGIT(r,6) = r6;
|
||||
MP_DIGIT(r,5) = r5;
|
||||
MP_DIGIT(r,4) = r4;
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r7 == MP_DIGIT_MAX) &&
|
||||
((r6 > 1) || ((r6 == 1) &&
|
||||
(r5 || r4 || r3 ||
|
||||
((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX)
|
||||
&& (r0 == MP_DIGIT_MAX)))))) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
#ifdef notdef
|
||||
|
||||
|
||||
/* smooth the negatives */
|
||||
while (MP_SIGN(r) != MP_ZPOS) {
|
||||
MP_CHECKOK(mp_add(r, &meth->irr, r));
|
||||
}
|
||||
while (MP_USED(r) > 8) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
/* final reduction if necessary */
|
||||
if (MP_DIGIT(r,7) >= MP_DIGIT(&meth->irr,7)) {
|
||||
if (mp_cmp(r,&meth->irr) != MP_LT) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a,7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a,6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a,5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a,4);
|
||||
}
|
||||
a7l = a7 << 32;
|
||||
a7h = a7 >> 32;
|
||||
a6l = a6 << 32;
|
||||
a6h = a6 >> 32;
|
||||
a5l = a5 << 32;
|
||||
a5h = a5 >> 32;
|
||||
a4l = a4 << 32;
|
||||
a4h = a4 >> 32;
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r0 = MP_DIGIT(a,0);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY_ZERO(r1, a5h << 32, r1, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 = carry;
|
||||
MP_ADD_CARRY_ZERO(r1, a5h << 32, r1, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY_ZERO(r1, a6l, r1, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
MP_ADD_CARRY_ZERO(r1, a6l, r1, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
|
||||
/* sum 3 */
|
||||
MP_ADD_CARRY_ZERO(r0, a4, r0, carry);
|
||||
MP_ADD_CARRY(r1, a5l >> 32, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 4 */
|
||||
MP_ADD_CARRY_ZERO(r0, a4h | a5l, r0, carry);
|
||||
MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a7, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a6h | a4l, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a5h | a6l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6h, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, (a4l>>32)|a5l,r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a6, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a4h|(a5h<<32),r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a6h|a7l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7h|a4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a4h|a5l, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6l, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a7, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a4h<<32, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a5, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6h<<32, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r4 > 0) {
|
||||
mp_digit r4_long = r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_ADD_CARRY_ZERO(r0, r4_long, r0, carry);
|
||||
MP_ADD_CARRY(r1, -r4l, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r4 < 0) {
|
||||
mp_digit r4_long = -r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_SUB_BORROW(r0, r4_long, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, -r4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = -carry;
|
||||
}
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,4));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r3 > 0xFFFFFFFF00000001ULL) ||
|
||||
((r3 == 0xFFFFFFFF00000001ULL) &&
|
||||
(r2 || (r1 >> 32)||
|
||||
(r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) {
|
||||
/* very rare, just use mp_sub */
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p256. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p256.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp256_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p256.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p256. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp256(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P256) {
|
||||
group->meth->field_mod = &ec_GFp_nistp256_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp256_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp256_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,294 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r.
|
||||
* Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m[10];
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit s[10][12];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 12;
|
||||
MP_USED(&m[i]) = 12;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#else
|
||||
mp_digit s[10][6];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 6;
|
||||
MP_USED(&m[i]) = 6;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = 0;
|
||||
s[1][3] = 0;
|
||||
s[1][4] = MP_DIGIT(a, 21);
|
||||
s[1][5] = MP_DIGIT(a, 22);
|
||||
s[1][6] = MP_DIGIT(a, 23);
|
||||
s[1][7] = 0;
|
||||
s[1][8] = 0;
|
||||
s[1][9] = 0;
|
||||
s[1][10] = 0;
|
||||
s[1][11] = 0;
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+12);
|
||||
}
|
||||
s[3][0] = MP_DIGIT(a, 21);
|
||||
s[3][1] = MP_DIGIT(a, 22);
|
||||
s[3][2] = MP_DIGIT(a, 23);
|
||||
for (i = 3; i < 12; i++) {
|
||||
s[3][i] = MP_DIGIT(a, i+9);
|
||||
}
|
||||
s[4][0] = 0;
|
||||
s[4][1] = MP_DIGIT(a, 23);
|
||||
s[4][2] = 0;
|
||||
s[4][3] = MP_DIGIT(a, 20);
|
||||
for (i = 4; i < 12; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+8);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = 0;
|
||||
s[5][3] = 0;
|
||||
s[5][4] = MP_DIGIT(a, 20);
|
||||
s[5][5] = MP_DIGIT(a, 21);
|
||||
s[5][6] = MP_DIGIT(a, 22);
|
||||
s[5][7] = MP_DIGIT(a, 23);
|
||||
s[5][8] = 0;
|
||||
s[5][9] = 0;
|
||||
s[5][10] = 0;
|
||||
s[5][11] = 0;
|
||||
s[6][0] = MP_DIGIT(a, 20);
|
||||
s[6][1] = 0;
|
||||
s[6][2] = 0;
|
||||
s[6][3] = MP_DIGIT(a, 21);
|
||||
s[6][4] = MP_DIGIT(a, 22);
|
||||
s[6][5] = MP_DIGIT(a, 23);
|
||||
s[6][6] = 0;
|
||||
s[6][7] = 0;
|
||||
s[6][8] = 0;
|
||||
s[6][9] = 0;
|
||||
s[6][10] = 0;
|
||||
s[6][11] = 0;
|
||||
s[7][0] = MP_DIGIT(a, 23);
|
||||
for (i = 1; i < 12; i++) {
|
||||
s[7][i] = MP_DIGIT(a, i+11);
|
||||
}
|
||||
s[8][0] = 0;
|
||||
s[8][1] = MP_DIGIT(a, 20);
|
||||
s[8][2] = MP_DIGIT(a, 21);
|
||||
s[8][3] = MP_DIGIT(a, 22);
|
||||
s[8][4] = MP_DIGIT(a, 23);
|
||||
s[8][5] = 0;
|
||||
s[8][6] = 0;
|
||||
s[8][7] = 0;
|
||||
s[8][8] = 0;
|
||||
s[8][9] = 0;
|
||||
s[8][10] = 0;
|
||||
s[8][11] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = 0;
|
||||
s[9][2] = 0;
|
||||
s[9][3] = MP_DIGIT(a, 23);
|
||||
s[9][4] = MP_DIGIT(a, 23);
|
||||
s[9][5] = 0;
|
||||
s[9][6] = 0;
|
||||
s[9][7] = 0;
|
||||
s[9][8] = 0;
|
||||
s[9][9] = 0;
|
||||
s[9][10] = 0;
|
||||
s[9][11] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#else
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[1][3] = MP_DIGIT(a, 11) >> 32;
|
||||
s[1][4] = 0;
|
||||
s[1][5] = 0;
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+6);
|
||||
}
|
||||
s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32);
|
||||
}
|
||||
s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[4][1] = MP_DIGIT(a, 10) << 32;
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+4);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = MP_DIGIT(a, 10);
|
||||
s[5][3] = MP_DIGIT(a, 11);
|
||||
s[5][4] = 0;
|
||||
s[5][5] = 0;
|
||||
s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32;
|
||||
s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32;
|
||||
s[6][2] = MP_DIGIT(a, 11);
|
||||
s[6][3] = 0;
|
||||
s[6][4] = 0;
|
||||
s[6][5] = 0;
|
||||
s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 1; i < 6; i++) {
|
||||
s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32);
|
||||
}
|
||||
s[8][0] = MP_DIGIT(a, 10) << 32;
|
||||
s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[8][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[8][3] = 0;
|
||||
s[8][4] = 0;
|
||||
s[8][5] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[9][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[9][3] = 0;
|
||||
s[9][4] = 0;
|
||||
s[9][5] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p384. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p384.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p384.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p384. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp384(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P384) {
|
||||
group->meth->field_mod = &ec_GFp_nistp384_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp384_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp384_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define ECP521_DIGITS ECL_CURVE_DIGITS(521)
|
||||
|
||||
/* Fast modular reduction for p521 = 2^521 - 1. a can be r. Uses
|
||||
* algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
unsigned int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m1;
|
||||
|
||||
mp_digit s1[ECP521_DIGITS] = { 0 };
|
||||
|
||||
MP_SIGN(&m1) = MP_ZPOS;
|
||||
MP_ALLOC(&m1) = ECP521_DIGITS;
|
||||
MP_USED(&m1) = ECP521_DIGITS;
|
||||
MP_DIGITS(&m1) = s1;
|
||||
|
||||
if (a_bits < 521) {
|
||||
if (a==r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if (a_bits > (521*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#define FIRST_DIGIT (ECP521_DIGITS-1)
|
||||
for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) {
|
||||
s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9)
|
||||
| (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9));
|
||||
}
|
||||
s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9;
|
||||
|
||||
if ( a != r ) {
|
||||
MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS));
|
||||
for (i = 0; i < ECP521_DIGITS; i++) {
|
||||
MP_DIGIT(r,i) = MP_DIGIT(a, i);
|
||||
}
|
||||
}
|
||||
MP_USED(r) = ECP521_DIGITS;
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
|
||||
MP_CHECKOK(s_mp_add(r, &m1));
|
||||
if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) {
|
||||
MP_CHECKOK(s_mp_add_d(r,1));
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
}
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p521. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p521.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p521.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p521. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t, FLAG(b)));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp521(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P521) {
|
||||
group->meth->field_mod = &ec_GFp_nistp521_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp521_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp521_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp521_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,360 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. Assumes input
|
||||
* is already field-encoded using field_enc, and returns output that is
|
||||
* still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, temp, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&temp) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&temp, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&tempx, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&tempy, FLAG(px)));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py-qy) / (px-qx) */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qy = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = (3qx^2+a) / (2qy) */
|
||||
MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 3));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempx, &temp, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 2));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempx, &tempy, &lambda, group->meth));
|
||||
}
|
||||
/* rx = lambda^2 - px - qx */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
|
||||
/* ry = (x1-x2) * lambda - y1 */
|
||||
MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
MP_CHECKOK(mp_copy(&tempy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&temp);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy, FLAG(px)));
|
||||
/* nqy = -qy */
|
||||
MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth));
|
||||
res = group->point_add(px, py, qx, &nqy, rx, ry, group);
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err
|
||||
ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&accr, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&tmp, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&pxt, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&pyt, FLAG(px)));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
/* timing mitigation is not supported */
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) );
|
||||
if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
@ -1,564 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). P and R can share x and y coordinates.
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2, z3;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_DIGITS(&z3) = 0;
|
||||
MP_CHECKOK(mp_init(&z1, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&z2, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&z3, FLAG(px)));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz^2, py / pz^3) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
mp_clear(&z3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Jacobian-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (2) from Brown, Hankerson, Lopez, and
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, C2, C3;
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&C2) = 0;
|
||||
MP_DIGITS(&C3) = 0;
|
||||
MP_CHECKOK(mp_init(&A, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&B, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&C, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&D, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&C2, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&C3, FLAG(px)));
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
|
||||
|
||||
/*
|
||||
* Additional checks for point equality and point at infinity
|
||||
*/
|
||||
if (mp_cmp(px, &A) == 0 && mp_cmp(py, &B) == 0) {
|
||||
/* POINT_DOUBLE(P) */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(px, py, pz, rx, ry, rz, group));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&C2);
|
||||
mp_clear(&C3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* This routine implements Point Doubling in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1, M, S;
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&M) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
MP_CHECKOK(mp_init(&t0, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&t1, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&M, FLAG(px)));
|
||||
MP_CHECKOK(mp_init(&S, FLAG(px)));
|
||||
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
/* M = 3 * px^2 + a */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&t0, &group->curvea, &M, group->meth));
|
||||
} else if (mp_cmp_int(&group->curvea, -3, FLAG(px)) == 0) {
|
||||
/* M = 3 * (px + pz^2) * (px - pz^2) */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, &M, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &M, group->meth));
|
||||
} else {
|
||||
/* M = 3 * (px^2) + a * (pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&M, &group->curvea, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &t0, &M, group->meth));
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
/* t0 = 4 * py^2 */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, &t0, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, pz, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
}
|
||||
|
||||
/* S = 4 * px * py^2 = px * (2 * py)^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &t0, &S, group->meth));
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
MP_CHECKOK(group->meth->field_add(&S, &S, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, &t1, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t1, group->meth));
|
||||
if (mp_isodd(&t1)) {
|
||||
MP_CHECKOK(mp_add(&t1, &group->meth->irr, &t1));
|
||||
}
|
||||
MP_CHECKOK(mp_div_2(&t1, &t1));
|
||||
MP_CHECKOK(group->meth->field_sub(&S, rx, &S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&M, &S, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&M, &t1, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
mp_clear(&M);
|
||||
mp_clear(&S);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
int i, ni, d;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Uses mixed Jacobian-affine coordinates. Input and output values are
|
||||
* assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous
|
||||
* multiple point multiplication) from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group, int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
mp_int rz;
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
MP_DIGITS(&rz) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry, timing);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][0], FLAG(k1)));
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][1], FLAG(k1)));
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz, FLAG(k1)));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1],
|
||||
rx, ry, &rz, group));
|
||||
}
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
@ -1,396 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math library for prime field curves.
|
||||
*
|
||||
* 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):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: May 2017
|
||||
*********************************************************************** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "mplogic.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define MAX_SCRATCH 6
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Modified Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *t0, *t1, *M, *S;
|
||||
|
||||
t0 = &scratch[0];
|
||||
t1 = &scratch[1];
|
||||
M = &scratch[2];
|
||||
S = &scratch[3];
|
||||
|
||||
#if MAX_SCRATCH < 4
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth));
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth));
|
||||
|
||||
/* t0 = 2y^2 , t1 = 8y^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth));
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, S, group->meth));
|
||||
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - t1 */
|
||||
MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth));
|
||||
|
||||
/* ra*z^4 = 2*t1*(apz4) */
|
||||
MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth));
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *A, *B, *C, *D, *C2, *C3;
|
||||
|
||||
A = &scratch[0];
|
||||
B = &scratch[1];
|
||||
C = &scratch[2];
|
||||
D = &scratch[3];
|
||||
C2 = &scratch[4];
|
||||
C3 = &scratch[5];
|
||||
|
||||
#if MAX_SCRATCH < 6
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
MP_CHECKOK(mp_copy(paz4, raz4));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
|
||||
|
||||
/*
|
||||
* Additional checks for point equality and point at infinity
|
||||
*/
|
||||
if (mp_cmp(px, A) == 0 && mp_cmp(py, B) == 0) {
|
||||
/* POINT_DOUBLE(P) */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jm(px, py, pz, paz4, rx, ry, rz, raz4,
|
||||
scratch, group));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(D, A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth));
|
||||
|
||||
/* raz4 = a * rz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group,
|
||||
int timing)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz, tpx, tpy, tpz;
|
||||
mp_int raz4, tpaz4;
|
||||
mp_int scratch[MAX_SCRATCH];
|
||||
signed char *naf = NULL;
|
||||
int i, orderBitSize;
|
||||
int numDoubles, numAdds, extraDoubles, extraAdds;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_DIGITS(&raz4) = 0;
|
||||
MP_DIGITS(&tpx) = 0;
|
||||
MP_DIGITS(&tpy) = 0;
|
||||
MP_DIGITS(&tpz) = 0;
|
||||
MP_DIGITS(&tpaz4) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_DIGITS(&scratch[i]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
MP_CHECKOK(mp_init(&tpx, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&tpy, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&tpz, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&tpaz4, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&rz, FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&raz4, FLAG(n)));
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0], FLAG(n)));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1], FLAG(n)));
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_CHECKOK(mp_init(&scratch[i], FLAG(n)));
|
||||
}
|
||||
|
||||
/* Set out[8] = P */
|
||||
MP_CHECKOK(mp_copy(px, &precomp[8][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[8][1]));
|
||||
|
||||
/* Set (tpx, tpy) = 2P */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
|
||||
group));
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
for (i = 8; i < 15; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
|
||||
&precomp[i + 1][0], &precomp[i + 1][1],
|
||||
group));
|
||||
}
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
for (i = 0; i < 8; i++) {
|
||||
MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_neg(&precomp[15 - i][1], &precomp[i][1],
|
||||
group->meth));
|
||||
}
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
orderBitSize = mpl_significant_bits(&group->order);
|
||||
|
||||
/* Allocate memory for NAF */
|
||||
#ifdef _KERNEL
|
||||
naf = (signed char *) kmem_alloc((orderBitSize + 1), FLAG(n));
|
||||
#else
|
||||
naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
|
||||
if (naf == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, orderBitSize, n, 5);
|
||||
|
||||
numAdds = 0;
|
||||
numDoubles = orderBitSize;
|
||||
/* wNAF method */
|
||||
for (i = orderBitSize; i >= 0; i--) {
|
||||
|
||||
if (ec_GFp_pt_is_inf_jac(rx, ry, &rz) == MP_YES) {
|
||||
numDoubles--;
|
||||
}
|
||||
|
||||
/* R = 2R */
|
||||
ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
|
||||
&raz4, scratch, group);
|
||||
|
||||
if (naf[i] != 0) {
|
||||
ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
|
||||
&precomp[(naf[i] + 15) / 2][0],
|
||||
&precomp[(naf[i] + 15) / 2][1], rx, ry,
|
||||
&rz, &raz4, scratch, group);
|
||||
numAdds++;
|
||||
}
|
||||
}
|
||||
|
||||
/* extra operations to make timing less dependent on secrets */
|
||||
if (timing) {
|
||||
/* low-order bit of timing argument contains no entropy */
|
||||
timing >>= 1;
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(&tpx, &tpy, &tpz));
|
||||
mp_zero(&tpaz4);
|
||||
|
||||
/* Set the temp value to a non-infinite point */
|
||||
ec_GFp_pt_add_jm_aff(&tpx, &tpy, &tpz, &tpaz4,
|
||||
&precomp[8][0],
|
||||
&precomp[8][1], &tpx, &tpy,
|
||||
&tpz, &tpaz4, scratch, group);
|
||||
|
||||
/* two bits of extra adds */
|
||||
extraAdds = timing & 0x3;
|
||||
timing >>= 2;
|
||||
/* Window size is 5, so the maximum number of additions is ceil(orderBitSize/5) */
|
||||
/* This is the same as (orderBitSize + 4) / 5 */
|
||||
for(i = numAdds; i <= (orderBitSize + 4) / 5 + extraAdds; i++) {
|
||||
ec_GFp_pt_add_jm_aff(&tpx, &tpy, &tpz, &tpaz4,
|
||||
&precomp[9 + (i % 3)][0],
|
||||
&precomp[9 + (i % 3)][1], &tpx, &tpy,
|
||||
&tpz, &tpaz4, scratch, group);
|
||||
}
|
||||
|
||||
/* two bits of extra doubles */
|
||||
extraDoubles = timing & 0x3;
|
||||
timing >>= 2;
|
||||
for(i = numDoubles; i <= orderBitSize + extraDoubles; i++) {
|
||||
ec_GFp_pt_dbl_jm(&tpx, &tpy, &tpz, &tpaz4, &tpx, &tpy, &tpz,
|
||||
&tpaz4, scratch, group);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
mp_clear(&scratch[i]);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
mp_clear(&tpx);
|
||||
mp_clear(&tpy);
|
||||
mp_clear(&tpz);
|
||||
mp_clear(&tpaz4);
|
||||
mp_clear(&rz);
|
||||
mp_clear(&raz4);
|
||||
#ifdef _KERNEL
|
||||
kmem_free(naf, (orderBitSize + 1));
|
||||
#else
|
||||
free(naf);
|
||||
#endif
|
||||
return res;
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 math 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):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* Uses Montgomery reduction for field arithmetic. See mpi/mpmontg.c for
|
||||
* code implementation. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ecp.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* Construct a generic GFMethod for arithmetic over prime fields with
|
||||
* irreducible irr. */
|
||||
GFMethod *
|
||||
GFMethod_consGFp_mont(const mp_int *irr)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int i;
|
||||
GFMethod *meth = NULL;
|
||||
mp_mont_modulus *mmm;
|
||||
|
||||
meth = GFMethod_consGFp(irr);
|
||||
if (meth == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef _KERNEL
|
||||
mmm = (mp_mont_modulus *) kmem_alloc(sizeof(mp_mont_modulus),
|
||||
FLAG(irr));
|
||||
#else
|
||||
mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus));
|
||||
#endif
|
||||
if (mmm == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
meth->field_mul = &ec_GFp_mul_mont;
|
||||
meth->field_sqr = &ec_GFp_sqr_mont;
|
||||
meth->field_div = &ec_GFp_div_mont;
|
||||
meth->field_enc = &ec_GFp_enc_mont;
|
||||
meth->field_dec = &ec_GFp_dec_mont;
|
||||
meth->extra1 = mmm;
|
||||
meth->extra2 = NULL;
|
||||
meth->extra_free = &ec_GFp_extra_free_mont;
|
||||
|
||||
mmm->N = meth->irr;
|
||||
i = mpl_significant_bits(&meth->irr);
|
||||
i += MP_DIGIT_BIT - 1;
|
||||
mmm->b = i - i % MP_DIGIT_BIT;
|
||||
mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
GFMethod_free(meth);
|
||||
return NULL;
|
||||
}
|
||||
return meth;
|
||||
}
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
|
||||
/* Field multiplication using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
#ifdef MP_MONT_USE_MP_MUL
|
||||
/* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont
|
||||
* is not implemented and we have to use mp_mul and s_mp_redc directly
|
||||
*/
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1));
|
||||
#else
|
||||
mp_int s;
|
||||
|
||||
MP_DIGITS(&s) = 0;
|
||||
/* s_mp_mul_mont doesn't allow source and destination to be the same */
|
||||
if ((a == r) || (b == r)) {
|
||||
MP_CHECKOK(mp_init(&s, FLAG(a)));
|
||||
MP_CHECKOK(s_mp_mul_mont
|
||||
(a, b, &s, (mp_mont_modulus *) meth->extra1));
|
||||
MP_CHECKOK(mp_copy(&s, r));
|
||||
mp_clear(&s);
|
||||
} else {
|
||||
return s_mp_mul_mont(a, b, r, (mp_mont_modulus *) meth->extra1);
|
||||
}
|
||||
#endif
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Field squaring using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
return ec_GFp_mul_mont(a, a, r, meth);
|
||||
}
|
||||
|
||||
/* Field division using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* if A=aZ represents a encoded in montgomery coordinates with Z and #
|
||||
* and \ respectively represent multiplication and division in
|
||||
* montgomery coordinates, then A\B = (a/b)Z = (A/B)Z and Binv =
|
||||
* (1/b)Z = (1/B)(Z^2) where B # Binv = Z */
|
||||
MP_CHECKOK(ec_GFp_div(a, b, r, meth));
|
||||
MP_CHECKOK(ec_GFp_enc_mont(r, r, meth));
|
||||
if (a == NULL) {
|
||||
MP_CHECKOK(ec_GFp_enc_mont(r, r, meth));
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Encode a field element in Montgomery form. See s_mp_to_mont in
|
||||
* mpi/mpmontg.c */
|
||||
mp_err
|
||||
ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_mont_modulus *mmm;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
mmm = (mp_mont_modulus *) meth->extra1;
|
||||
MP_CHECKOK(mpl_lsh(a, r, mmm->b));
|
||||
MP_CHECKOK(mp_mod(r, &mmm->N, r));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Decode a field element from Montgomery form. */
|
||||
mp_err
|
||||
ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Free the memory allocated to the extra fields of Montgomery GFMethod
|
||||
* object. */
|
||||
void
|
||||
ec_GFp_extra_free_mont(GFMethod *meth)
|
||||
{
|
||||
if (meth->extra1 != NULL) {
|
||||
#ifdef _KERNEL
|
||||
kmem_free(meth->extra1, sizeof(mp_mont_modulus));
|
||||
#else
|
||||
free(meth->extra1);
|
||||
#endif
|
||||
meth->extra1 = NULL;
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _LOGTAB_H
|
||||
#define _LOGTAB_H
|
||||
|
||||
const float s_logv_2[] = {
|
||||
0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */
|
||||
0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */
|
||||
0.333333333f, 0.315464877f, 0.301029996f, 0.289064826f, /* 8 9 10 11 */
|
||||
0.278942946f, 0.270238154f, 0.262649535f, 0.255958025f, /* 12 13 14 15 */
|
||||
0.250000000f, 0.244650542f, 0.239812467f, 0.235408913f, /* 16 17 18 19 */
|
||||
0.231378213f, 0.227670249f, 0.224243824f, 0.221064729f, /* 20 21 22 23 */
|
||||
0.218104292f, 0.215338279f, 0.212746054f, 0.210309918f, /* 24 25 26 27 */
|
||||
0.208014598f, 0.205846832f, 0.203795047f, 0.201849087f, /* 28 29 30 31 */
|
||||
0.200000000f, 0.198239863f, 0.196561632f, 0.194959022f, /* 32 33 34 35 */
|
||||
0.193426404f, 0.191958720f, 0.190551412f, 0.189200360f, /* 36 37 38 39 */
|
||||
0.187901825f, 0.186652411f, 0.185449023f, 0.184288833f, /* 40 41 42 43 */
|
||||
0.183169251f, 0.182087900f, 0.181042597f, 0.180031327f, /* 44 45 46 47 */
|
||||
0.179052232f, 0.178103594f, 0.177183820f, 0.176291434f, /* 48 49 50 51 */
|
||||
0.175425064f, 0.174583430f, 0.173765343f, 0.172969690f, /* 52 53 54 55 */
|
||||
0.172195434f, 0.171441601f, 0.170707280f, 0.169991616f, /* 56 57 58 59 */
|
||||
0.169293808f, 0.168613099f, 0.167948779f, 0.167300179f, /* 60 61 62 63 */
|
||||
0.166666667f
|
||||
};
|
||||
|
||||
#endif /* _LOGTAB_H */
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Multi-precision Binary Polynomial Arithmetic 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):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _MP_GF2M_PRIV_H_
|
||||
#define _MP_GF2M_PRIV_H_
|
||||
|
||||
#include "mpi-priv.h"
|
||||
|
||||
extern const mp_digit mp_gf2m_sqr_tb[16];
|
||||
|
||||
#if defined(MP_USE_UINT_DIGIT)
|
||||
#define MP_DIGIT_BITS 32
|
||||
#else
|
||||
#define MP_DIGIT_BITS 64
|
||||
#endif
|
||||
|
||||
/* Platform-specific macros for fast binary polynomial squaring. */
|
||||
#if MP_DIGIT_BITS == 32
|
||||
#define gf2m_SQR1(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF]
|
||||
#define gf2m_SQR0(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
|
||||
#else
|
||||
#define gf2m_SQR1(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 60 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 56 & 0xF] << 48 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 52 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 48 & 0xF] << 32 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 44 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 40 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 36 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 32 & 0xF]
|
||||
#define gf2m_SQR0(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 48 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] << 32 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
|
||||
#endif
|
||||
|
||||
/* Multiply two binary polynomials mp_digits a, b.
|
||||
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
|
||||
* Output in two mp_digits rh, rl.
|
||||
*/
|
||||
void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
|
||||
* result is a binary polynomial in 4 mp_digits r[4].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
|
||||
const mp_digit b0);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
|
||||
* result is a binary polynomial in 6 mp_digits r[6].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
|
||||
const mp_digit b2, const mp_digit b1, const mp_digit b0);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
|
||||
* result is a binary polynomial in 8 mp_digits r[8].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
|
||||
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
|
||||
const mp_digit b0);
|
||||
|
||||
#endif /* _MP_GF2M_PRIV_H_ */
|
@ -1,603 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Multi-precision Binary Polynomial Arithmetic 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):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
|
||||
const mp_digit mp_gf2m_sqr_tb[16] =
|
||||
{
|
||||
0, 1, 4, 5, 16, 17, 20, 21,
|
||||
64, 65, 68, 69, 80, 81, 84, 85
|
||||
};
|
||||
|
||||
/* Multiply two binary polynomials mp_digits a, b.
|
||||
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
|
||||
* Output in two mp_digits rh, rl.
|
||||
*/
|
||||
#if MP_DIGIT_BITS == 32
|
||||
void
|
||||
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
|
||||
{
|
||||
register mp_digit h, l, s;
|
||||
mp_digit tab[8], top2b = a >> 30;
|
||||
register mp_digit a1, a2, a4;
|
||||
|
||||
a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
|
||||
|
||||
tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
|
||||
tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
|
||||
|
||||
s = tab[b & 0x7]; l = s;
|
||||
s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29;
|
||||
s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26;
|
||||
s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23;
|
||||
s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
|
||||
s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
|
||||
s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
|
||||
s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
|
||||
s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8;
|
||||
s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5;
|
||||
s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2;
|
||||
|
||||
/* compensate for the top two bits of a */
|
||||
|
||||
if (top2b & 01) { l ^= b << 30; h ^= b >> 2; }
|
||||
if (top2b & 02) { l ^= b << 31; h ^= b >> 1; }
|
||||
|
||||
*rh = h; *rl = l;
|
||||
}
|
||||
#else
|
||||
void
|
||||
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
|
||||
{
|
||||
register mp_digit h, l, s;
|
||||
mp_digit tab[16], top3b = a >> 61;
|
||||
register mp_digit a1, a2, a4, a8;
|
||||
|
||||
a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1;
|
||||
a4 = a2 << 1; a8 = a4 << 1;
|
||||
tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2;
|
||||
tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4;
|
||||
tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8;
|
||||
tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
|
||||
|
||||
s = tab[b & 0xF]; l = s;
|
||||
s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60;
|
||||
s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56;
|
||||
s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
|
||||
s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
|
||||
s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
|
||||
s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
|
||||
s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
|
||||
s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
|
||||
s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
|
||||
s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
|
||||
s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
|
||||
s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
|
||||
s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
|
||||
s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8;
|
||||
s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4;
|
||||
|
||||
/* compensate for the top three bits of a */
|
||||
|
||||
if (top3b & 01) { l ^= b << 61; h ^= b >> 3; }
|
||||
if (top3b & 02) { l ^= b << 62; h ^= b >> 2; }
|
||||
if (top3b & 04) { l ^= b << 63; h ^= b >> 1; }
|
||||
|
||||
*rh = h; *rl = l;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
|
||||
* result is a binary polynomial in 4 mp_digits r[4].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void
|
||||
s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
|
||||
const mp_digit b0)
|
||||
{
|
||||
mp_digit m1, m0;
|
||||
/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
|
||||
s_bmul_1x1(r+3, r+2, a1, b1);
|
||||
s_bmul_1x1(r+1, r, a0, b0);
|
||||
s_bmul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
|
||||
/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
|
||||
r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */
|
||||
r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
|
||||
}
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
|
||||
* result is a binary polynomial in 6 mp_digits r[6].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void
|
||||
s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
|
||||
const mp_digit b2, const mp_digit b1, const mp_digit b0)
|
||||
{
|
||||
mp_digit zm[4];
|
||||
|
||||
s_bmul_1x1(r+5, r+4, a2, b2); /* fill top 2 words */
|
||||
s_bmul_2x2(zm, a1, a2^a0, b1, b2^b0); /* fill middle 4 words */
|
||||
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
|
||||
|
||||
zm[3] ^= r[3];
|
||||
zm[2] ^= r[2];
|
||||
zm[1] ^= r[1] ^ r[5];
|
||||
zm[0] ^= r[0] ^ r[4];
|
||||
|
||||
r[5] ^= zm[3];
|
||||
r[4] ^= zm[2];
|
||||
r[3] ^= zm[1];
|
||||
r[2] ^= zm[0];
|
||||
}
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
|
||||
* result is a binary polynomial in 8 mp_digits r[8].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
|
||||
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
|
||||
const mp_digit b0)
|
||||
{
|
||||
mp_digit zm[4];
|
||||
|
||||
s_bmul_2x2(r+4, a3, a2, b3, b2); /* fill top 4 words */
|
||||
s_bmul_2x2(zm, a3^a1, a2^a0, b3^b1, b2^b0); /* fill middle 4 words */
|
||||
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
|
||||
|
||||
zm[3] ^= r[3] ^ r[7];
|
||||
zm[2] ^= r[2] ^ r[6];
|
||||
zm[1] ^= r[1] ^ r[5];
|
||||
zm[0] ^= r[0] ^ r[4];
|
||||
|
||||
r[5] ^= zm[3];
|
||||
r[4] ^= zm[2];
|
||||
r[3] ^= zm[1];
|
||||
r[2] ^= zm[0];
|
||||
}
|
||||
|
||||
/* Compute addition of two binary polynomials a and b,
|
||||
* store result in c; c could be a or b, a and b could be equal;
|
||||
* c is the bitwise XOR of a and b.
|
||||
*/
|
||||
mp_err
|
||||
mp_badd(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_digit *pa, *pb, *pc;
|
||||
mp_size ix;
|
||||
mp_size used_pa, used_pb;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* Add all digits up to the precision of b. If b had more
|
||||
* precision than a initially, swap a, b first
|
||||
*/
|
||||
if (MP_USED(a) >= MP_USED(b)) {
|
||||
pa = MP_DIGITS(a);
|
||||
pb = MP_DIGITS(b);
|
||||
used_pa = MP_USED(a);
|
||||
used_pb = MP_USED(b);
|
||||
} else {
|
||||
pa = MP_DIGITS(b);
|
||||
pb = MP_DIGITS(a);
|
||||
used_pa = MP_USED(b);
|
||||
used_pb = MP_USED(a);
|
||||
}
|
||||
|
||||
/* Make sure c has enough precision for the output value */
|
||||
MP_CHECKOK( s_mp_pad(c, used_pa) );
|
||||
|
||||
/* Do word-by-word xor */
|
||||
pc = MP_DIGITS(c);
|
||||
for (ix = 0; ix < used_pb; ix++) {
|
||||
(*pc++) = (*pa++) ^ (*pb++);
|
||||
}
|
||||
|
||||
/* Finish the rest of digits until we're actually done */
|
||||
for (; ix < used_pa; ++ix) {
|
||||
*pc++ = *pa++;
|
||||
}
|
||||
|
||||
MP_USED(c) = used_pa;
|
||||
MP_SIGN(c) = ZPOS;
|
||||
s_mp_clamp(c);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#define s_mp_div2(a) MP_CHECKOK( mpl_rsh((a), (a), 1) );
|
||||
|
||||
/* Compute binary polynomial multiply d = a * b */
|
||||
static void
|
||||
s_bmul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
|
||||
{
|
||||
mp_digit a_i, a0b0, a1b1, carry = 0;
|
||||
while (a_len--) {
|
||||
a_i = *a++;
|
||||
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
|
||||
*d++ = a0b0 ^ carry;
|
||||
carry = a1b1;
|
||||
}
|
||||
*d = carry;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial xor multiply accumulate d ^= a * b */
|
||||
static void
|
||||
s_bmul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
|
||||
{
|
||||
mp_digit a_i, a0b0, a1b1, carry = 0;
|
||||
while (a_len--) {
|
||||
a_i = *a++;
|
||||
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
|
||||
*d++ ^= a0b0 ^ carry;
|
||||
carry = a1b1;
|
||||
}
|
||||
*d ^= carry;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial xor multiply c = a * b.
|
||||
* All parameters may be identical.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmul(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_digit *pb, b_i;
|
||||
mp_int tmp;
|
||||
mp_size ib, a_used, b_used;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (a == c) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, a) );
|
||||
if (a == b)
|
||||
b = &tmp;
|
||||
a = &tmp;
|
||||
} else if (b == c) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, b) );
|
||||
b = &tmp;
|
||||
}
|
||||
|
||||
if (MP_USED(a) < MP_USED(b)) {
|
||||
const mp_int *xch = b; /* switch a and b if b longer */
|
||||
b = a;
|
||||
a = xch;
|
||||
}
|
||||
|
||||
MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
|
||||
MP_CHECKOK( s_mp_pad(c, USED(a) + USED(b)) );
|
||||
|
||||
pb = MP_DIGITS(b);
|
||||
s_bmul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
|
||||
|
||||
/* Outer loop: Digits of b */
|
||||
a_used = MP_USED(a);
|
||||
b_used = MP_USED(b);
|
||||
MP_USED(c) = a_used + b_used;
|
||||
for (ib = 1; ib < b_used; ib++) {
|
||||
b_i = *pb++;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
if (b_i)
|
||||
s_bmul_d_add(MP_DIGITS(a), a_used, b_i, MP_DIGITS(c) + ib);
|
||||
else
|
||||
MP_DIGIT(c, ib + a_used) = b_i;
|
||||
}
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
SIGN(c) = ZPOS;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Compute modular reduction of a and store result in r.
|
||||
* r could be a.
|
||||
* For modular arithmetic, the irreducible polynomial f(t) is represented
|
||||
* as an array of int[], where f(t) is of the form:
|
||||
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
|
||||
* where m = p[0] > p[1] > ... > p[k] = 0.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
int j, k;
|
||||
int n, dN, d0, d1;
|
||||
mp_digit zz, *z, tmp;
|
||||
mp_size used;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* The algorithm does the reduction in place in r,
|
||||
* if a != r, copy a into r first so reduction can be done in r
|
||||
*/
|
||||
if (a != r) {
|
||||
MP_CHECKOK( mp_copy(a, r) );
|
||||
}
|
||||
z = MP_DIGITS(r);
|
||||
|
||||
/* start reduction */
|
||||
dN = p[0] / MP_DIGIT_BITS;
|
||||
used = MP_USED(r);
|
||||
|
||||
for (j = used - 1; j > dN;) {
|
||||
|
||||
zz = z[j];
|
||||
if (zz == 0) {
|
||||
j--; continue;
|
||||
}
|
||||
z[j] = 0;
|
||||
|
||||
for (k = 1; p[k] > 0; k++) {
|
||||
/* reducing component t^p[k] */
|
||||
n = p[0] - p[k];
|
||||
d0 = n % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
n /= MP_DIGIT_BITS;
|
||||
z[j-n] ^= (zz>>d0);
|
||||
if (d0)
|
||||
z[j-n-1] ^= (zz<<d1);
|
||||
}
|
||||
|
||||
/* reducing component t^0 */
|
||||
n = dN;
|
||||
d0 = p[0] % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
z[j-n] ^= (zz >> d0);
|
||||
if (d0)
|
||||
z[j-n-1] ^= (zz << d1);
|
||||
|
||||
}
|
||||
|
||||
/* final round of reduction */
|
||||
while (j == dN) {
|
||||
|
||||
d0 = p[0] % MP_DIGIT_BITS;
|
||||
zz = z[dN] >> d0;
|
||||
if (zz == 0) break;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
|
||||
/* clear up the top d1 bits */
|
||||
if (d0) z[dN] = (z[dN] << d1) >> d1;
|
||||
*z ^= zz; /* reduction t^0 component */
|
||||
|
||||
for (k = 1; p[k] > 0; k++) {
|
||||
/* reducing component t^p[k]*/
|
||||
n = p[k] / MP_DIGIT_BITS;
|
||||
d0 = p[k] % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
z[n] ^= (zz << d0);
|
||||
tmp = zz >> d1;
|
||||
if (d0 && tmp)
|
||||
z[n+1] ^= tmp;
|
||||
}
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p,
|
||||
* Store the result in r. r could be a or b; a could be b.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
if (a == b) return mp_bsqrmod(a, p, r);
|
||||
if ((res = mp_bmul(a, b, r) ) != MP_OKAY)
|
||||
return res;
|
||||
return mp_bmod(r, p, r);
|
||||
}
|
||||
|
||||
/* Compute binary polynomial squaring c = a*a mod p .
|
||||
* Parameter r and a can be identical.
|
||||
*/
|
||||
|
||||
mp_err
|
||||
mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_digit *pa, *pr, a_i;
|
||||
mp_int tmp;
|
||||
mp_size ia, a_used;
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && r != NULL, MP_BADARG);
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
if (a == r) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, a) );
|
||||
a = &tmp;
|
||||
}
|
||||
|
||||
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
|
||||
MP_CHECKOK( s_mp_pad(r, 2*USED(a)) );
|
||||
|
||||
pa = MP_DIGITS(a);
|
||||
pr = MP_DIGITS(r);
|
||||
a_used = MP_USED(a);
|
||||
MP_USED(r) = 2 * a_used;
|
||||
|
||||
for (ia = 0; ia < a_used; ia++) {
|
||||
a_i = *pa++;
|
||||
*pr++ = gf2m_SQR0(a_i);
|
||||
*pr++ = gf2m_SQR1(a_i);
|
||||
}
|
||||
|
||||
MP_CHECKOK( mp_bmod(r, p, r) );
|
||||
s_mp_clamp(r);
|
||||
SIGN(r) = ZPOS;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial y/x mod p, y divided by x, reduce modulo p.
|
||||
* Store the result in r. r could be x or y, and x could equal y.
|
||||
* Uses algorithm Modular_Division_GF(2^m) from
|
||||
* Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to
|
||||
* the Great Divide".
|
||||
*/
|
||||
int
|
||||
mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
|
||||
const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_int aa, bb, uu;
|
||||
mp_int *a, *b, *u, *v;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_DIGITS(&aa) = 0;
|
||||
MP_DIGITS(&bb) = 0;
|
||||
MP_DIGITS(&uu) = 0;
|
||||
|
||||
MP_CHECKOK( mp_init_copy(&aa, x) );
|
||||
MP_CHECKOK( mp_init_copy(&uu, y) );
|
||||
MP_CHECKOK( mp_init_copy(&bb, pp) );
|
||||
MP_CHECKOK( s_mp_pad(r, USED(pp)) );
|
||||
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
|
||||
|
||||
a = &aa; b= &bb; u=&uu; v=r;
|
||||
/* reduce x and y mod p */
|
||||
MP_CHECKOK( mp_bmod(a, p, a) );
|
||||
MP_CHECKOK( mp_bmod(u, p, u) );
|
||||
|
||||
while (!mp_isodd(a)) {
|
||||
s_mp_div2(a);
|
||||
if (mp_isodd(u)) {
|
||||
MP_CHECKOK( mp_badd(u, pp, u) );
|
||||
}
|
||||
s_mp_div2(u);
|
||||
}
|
||||
|
||||
do {
|
||||
if (mp_cmp_mag(b, a) > 0) {
|
||||
MP_CHECKOK( mp_badd(b, a, b) );
|
||||
MP_CHECKOK( mp_badd(v, u, v) );
|
||||
do {
|
||||
s_mp_div2(b);
|
||||
if (mp_isodd(v)) {
|
||||
MP_CHECKOK( mp_badd(v, pp, v) );
|
||||
}
|
||||
s_mp_div2(v);
|
||||
} while (!mp_isodd(b));
|
||||
}
|
||||
else if ((MP_DIGIT(a,0) == 1) && (MP_USED(a) == 1))
|
||||
break;
|
||||
else {
|
||||
MP_CHECKOK( mp_badd(a, b, a) );
|
||||
MP_CHECKOK( mp_badd(u, v, u) );
|
||||
do {
|
||||
s_mp_div2(a);
|
||||
if (mp_isodd(u)) {
|
||||
MP_CHECKOK( mp_badd(u, pp, u) );
|
||||
}
|
||||
s_mp_div2(u);
|
||||
} while (!mp_isodd(a));
|
||||
}
|
||||
} while (1);
|
||||
|
||||
MP_CHECKOK( mp_copy(u, r) );
|
||||
|
||||
CLEANUP:
|
||||
/* XXX this appears to be a memory leak in the NSS code */
|
||||
mp_clear(&aa);
|
||||
mp_clear(&bb);
|
||||
mp_clear(&uu);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/* Convert the bit-string representation of a polynomial a into an array
|
||||
* of integers corresponding to the bits with non-zero coefficient.
|
||||
* Up to max elements of the array will be filled. Return value is total
|
||||
* number of coefficients that would be extracted if array was large enough.
|
||||
*/
|
||||
int
|
||||
mp_bpoly2arr(const mp_int *a, unsigned int p[], int max)
|
||||
{
|
||||
int i, j, k;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
|
||||
for (k = 0; k < max; k++) p[k] = 0;
|
||||
k = 0;
|
||||
|
||||
for (i = MP_USED(a) - 1; i >= 0; i--) {
|
||||
mask = top_bit;
|
||||
for (j = MP_DIGIT_BIT - 1; j >= 0; j--) {
|
||||
if (MP_DIGITS(a)[i] & mask) {
|
||||
if (k < max) p[k] = MP_DIGIT_BIT * i + j;
|
||||
k++;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Convert the coefficient array representation of a polynomial to a
|
||||
* bit-string. The array must be terminated by 0.
|
||||
*/
|
||||
mp_err
|
||||
mp_barr2poly(const unsigned int p[], mp_int *a)
|
||||
{
|
||||
|
||||
mp_err res = MP_OKAY;
|
||||
int i;
|
||||
|
||||
mp_zero(a);
|
||||
for (i = 0; p[i] > 0; i++) {
|
||||
MP_CHECKOK( mpl_set_bit(a, p[i], 1) );
|
||||
}
|
||||
MP_CHECKOK( mpl_set_bit(a, 0, 1) );
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Multi-precision Binary Polynomial Arithmetic 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):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _MP_GF2M_H_
|
||||
#define _MP_GF2M_H_
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
mp_err mp_badd(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_bmul(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
|
||||
/* For modular arithmetic, the irreducible polynomial f(t) is represented
|
||||
* as an array of int[], where f(t) is of the form:
|
||||
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
|
||||
* where m = p[0] > p[1] > ... > p[k] = 0.
|
||||
*/
|
||||
mp_err mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r);
|
||||
mp_err mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[],
|
||||
mp_int *r);
|
||||
mp_err mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r);
|
||||
mp_err mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
|
||||
const unsigned int p[], mp_int *r);
|
||||
|
||||
int mp_bpoly2arr(const mp_int *a, unsigned int p[], int max);
|
||||
mp_err mp_barr2poly(const unsigned int p[], mp_int *a);
|
||||
|
||||
#endif /* _MP_GF2M_H_ */
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1997
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _MPI_CONFIG_H
|
||||
#define _MPI_CONFIG_H
|
||||
|
||||
/* $Id: mpi-config.h,v 1.5 2004/04/25 15:03:10 gerv%gerv.net Exp $ */
|
||||
|
||||
/*
|
||||
For boolean options,
|
||||
0 = no
|
||||
1 = yes
|
||||
|
||||
Other options are documented individually.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MP_IOFUNC
|
||||
#define MP_IOFUNC 0 /* include mp_print() ? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MODARITH
|
||||
#define MP_MODARITH 1 /* include modular arithmetic ? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_NUMTH
|
||||
#define MP_NUMTH 1 /* include number theoretic functions? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_LOGTAB
|
||||
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MEMSET
|
||||
#define MP_MEMSET 1 /* use memset() to zero buffers? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MEMCPY
|
||||
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_CRYPTO
|
||||
#define MP_CRYPTO 1 /* erase memory on free? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_ARGCHK
|
||||
/*
|
||||
0 = no parameter checks
|
||||
1 = runtime checks, continue execution and return an error to caller
|
||||
2 = assertions; dump core on parameter errors
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define MP_ARGCHK 2 /* how to check input arguments */
|
||||
#else
|
||||
#define MP_ARGCHK 1 /* how to check input arguments */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MP_DEBUG
|
||||
#define MP_DEBUG 0 /* print diagnostic output? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_DEFPREC
|
||||
#define MP_DEFPREC 64 /* default precision, in digits */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MACRO
|
||||
#define MP_MACRO 0 /* use macros for frequent calls? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_SQUARE
|
||||
#define MP_SQUARE 1 /* use separate squaring code? */
|
||||
#endif
|
||||
|
||||
#endif /* _MPI_CONFIG_H */
|
@ -1,320 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* NOTE WELL: the content of this header file is NOT part of the "public"
|
||||
* API for the MPI library, and may change at any time.
|
||||
* Application programs that use libmpi should NOT include this header file.
|
||||
*/
|
||||
|
||||
#ifndef _MPI_PRIV_H
|
||||
#define _MPI_PRIV_H
|
||||
|
||||
/* $Id: mpi-priv.h,v 1.20 2005/11/22 07:16:43 relyea%netscape.com Exp $ */
|
||||
|
||||
#include "mpi.h"
|
||||
#ifndef _KERNEL
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#if MP_DEBUG
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
|
||||
#else
|
||||
#define DIAG(T,V)
|
||||
#endif
|
||||
|
||||
/* If we aren't using a wired-in logarithm table, we need to include
|
||||
the math library to get the log() function
|
||||
*/
|
||||
|
||||
/* {{{ s_logv_2[] - log table for 2 in various bases */
|
||||
|
||||
#if MP_LOGTAB
|
||||
/*
|
||||
A table of the logs of 2 for various bases (the 0 and 1 entries of
|
||||
this table are meaningless and should not be referenced).
|
||||
|
||||
This table is used to compute output lengths for the mp_toradix()
|
||||
function. Since a number n in radix r takes up about log_r(n)
|
||||
digits, we estimate the output size by taking the least integer
|
||||
greater than log_r(n), where:
|
||||
|
||||
log_r(n) = log_2(n) * log_r(2)
|
||||
|
||||
This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
|
||||
which are the output bases supported.
|
||||
*/
|
||||
|
||||
extern const float s_logv_2[];
|
||||
#define LOG_V_2(R) s_logv_2[(R)]
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
If MP_LOGTAB is not defined, use the math library to compute the
|
||||
logarithms on the fly. Otherwise, use the table.
|
||||
Pick which works best for your system.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#define LOG_V_2(R) (log(2.0)/log(R))
|
||||
|
||||
#endif /* if MP_LOGTAB */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Digit arithmetic macros */
|
||||
|
||||
/*
|
||||
When adding and multiplying digits, the results can be larger than
|
||||
can be contained in an mp_digit. Thus, an mp_word is used. These
|
||||
macros mask off the upper and lower digits of the mp_word (the
|
||||
mp_word may be more than 2 mp_digits wide, but we only concern
|
||||
ourselves with the low-order 2 mp_digits)
|
||||
*/
|
||||
|
||||
#define CARRYOUT(W) (mp_digit)((W)>>DIGIT_BIT)
|
||||
#define ACCUM(W) (mp_digit)(W)
|
||||
|
||||
#define MP_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MP_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define MP_HOWMANY(a,b) (((a) + (b) - 1)/(b))
|
||||
#define MP_ROUNDUP(a,b) (MP_HOWMANY(a,b) * (b))
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Comparison constants */
|
||||
|
||||
#define MP_LT -1
|
||||
#define MP_EQ 0
|
||||
#define MP_GT 1
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ private function declarations */
|
||||
|
||||
/*
|
||||
If MP_MACRO is false, these will be defined as actual functions;
|
||||
otherwise, suitable macro definitions will be used. This works
|
||||
around the fact that ANSI C89 doesn't support an 'inline' keyword
|
||||
(although I hear C9x will ... about bloody time). At present, the
|
||||
macro definitions are identical to the function bodies, but they'll
|
||||
expand in place, instead of generating a function call.
|
||||
|
||||
I chose these particular functions to be made into macros because
|
||||
some profiling showed they are called a lot on a typical workload,
|
||||
and yet they are primarily housekeeping.
|
||||
*/
|
||||
#if MP_MACRO == 0
|
||||
void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */
|
||||
void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count); /* copy */
|
||||
void *s_mp_alloc(size_t nb, size_t ni, int flag); /* general allocator */
|
||||
void s_mp_free(void *ptr, mp_size); /* general free function */
|
||||
extern unsigned long mp_allocs;
|
||||
extern unsigned long mp_frees;
|
||||
extern unsigned long mp_copies;
|
||||
#else
|
||||
|
||||
/* Even if these are defined as macros, we need to respect the settings
|
||||
of the MP_MEMSET and MP_MEMCPY configuration options...
|
||||
*/
|
||||
#if MP_MEMSET == 0
|
||||
#define s_mp_setz(dp, count) \
|
||||
{int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
|
||||
#else
|
||||
#define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
|
||||
#endif /* MP_MEMSET */
|
||||
|
||||
#if MP_MEMCPY == 0
|
||||
#define s_mp_copy(sp, dp, count) \
|
||||
{int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
|
||||
#else
|
||||
#define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
|
||||
#endif /* MP_MEMCPY */
|
||||
|
||||
#define s_mp_alloc(nb, ni) calloc(nb, ni)
|
||||
#define s_mp_free(ptr) {if(ptr) free(ptr);}
|
||||
#endif /* MP_MACRO */
|
||||
|
||||
mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */
|
||||
mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */
|
||||
|
||||
#if MP_MACRO == 0
|
||||
void s_mp_clamp(mp_int *mp); /* clip leading zeroes */
|
||||
#else
|
||||
#define s_mp_clamp(mp)\
|
||||
{ mp_size used = MP_USED(mp); \
|
||||
while (used > 1 && DIGIT(mp, used - 1) == 0) --used; \
|
||||
MP_USED(mp) = used; \
|
||||
}
|
||||
#endif /* MP_MACRO */
|
||||
|
||||
void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */
|
||||
|
||||
mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */
|
||||
void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */
|
||||
mp_err s_mp_mul_2d(mp_int *mp, mp_digit d); /* multiply by 2^d in place */
|
||||
void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */
|
||||
void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */
|
||||
void s_mp_div_2(mp_int *mp); /* divide by 2 in place */
|
||||
mp_err s_mp_mul_2(mp_int *mp); /* multiply by 2 in place */
|
||||
mp_err s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd);
|
||||
/* normalize for division */
|
||||
mp_err s_mp_add_d(mp_int *mp, mp_digit d); /* unsigned digit addition */
|
||||
mp_err s_mp_sub_d(mp_int *mp, mp_digit d); /* unsigned digit subtract */
|
||||
mp_err s_mp_mul_d(mp_int *mp, mp_digit d); /* unsigned digit multiply */
|
||||
mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
|
||||
/* unsigned digit divide */
|
||||
mp_err s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);
|
||||
/* Barrett reduction */
|
||||
mp_err s_mp_add(mp_int *a, const mp_int *b); /* magnitude addition */
|
||||
mp_err s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err s_mp_sub(mp_int *a, const mp_int *b); /* magnitude subtract */
|
||||
mp_err s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset);
|
||||
/* a += b * RADIX^offset */
|
||||
mp_err s_mp_mul(mp_int *a, const mp_int *b); /* magnitude multiply */
|
||||
#if MP_SQUARE
|
||||
mp_err s_mp_sqr(mp_int *a); /* magnitude square */
|
||||
#else
|
||||
#define s_mp_sqr(a) s_mp_mul(a, a)
|
||||
#endif
|
||||
mp_err s_mp_div(mp_int *rem, mp_int *div, mp_int *quot); /* magnitude div */
|
||||
mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err s_mp_2expt(mp_int *a, mp_digit k); /* a = 2^k */
|
||||
int s_mp_cmp(const mp_int *a, const mp_int *b); /* magnitude comparison */
|
||||
int s_mp_cmp_d(const mp_int *a, mp_digit d); /* magnitude digit compare */
|
||||
int s_mp_ispow2(const mp_int *v); /* is v a power of 2? */
|
||||
int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */
|
||||
|
||||
int s_mp_tovalue(char ch, int r); /* convert ch to value */
|
||||
char s_mp_todigit(mp_digit val, int r, int low); /* convert val to digit */
|
||||
int s_mp_outlen(int bits, int r); /* output length in bytes */
|
||||
mp_digit s_mp_invmod_radix(mp_digit P); /* returns (P ** -1) mod RADIX */
|
||||
mp_err s_mp_invmod_odd_m( const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err s_mp_invmod_2d( const mp_int *a, mp_size k, mp_int *c);
|
||||
mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
|
||||
#ifdef NSS_USE_COMBA
|
||||
|
||||
#define IS_POWER_OF_2(a) ((a) && !((a) & ((a)-1)))
|
||||
|
||||
void s_mp_mul_comba_4(const mp_int *A, const mp_int *B, mp_int *C);
|
||||
void s_mp_mul_comba_8(const mp_int *A, const mp_int *B, mp_int *C);
|
||||
void s_mp_mul_comba_16(const mp_int *A, const mp_int *B, mp_int *C);
|
||||
void s_mp_mul_comba_32(const mp_int *A, const mp_int *B, mp_int *C);
|
||||
|
||||
void s_mp_sqr_comba_4(const mp_int *A, mp_int *B);
|
||||
void s_mp_sqr_comba_8(const mp_int *A, mp_int *B);
|
||||
void s_mp_sqr_comba_16(const mp_int *A, mp_int *B);
|
||||
void s_mp_sqr_comba_32(const mp_int *A, mp_int *B);
|
||||
|
||||
#endif /* end NSS_USE_COMBA */
|
||||
|
||||
/* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */
|
||||
#if defined (__OS2__) && defined (__IBMC__)
|
||||
#define MPI_ASM_DECL __cdecl
|
||||
#else
|
||||
#define MPI_ASM_DECL
|
||||
#endif
|
||||
|
||||
#ifdef MPI_AMD64
|
||||
|
||||
mp_digit MPI_ASM_DECL s_mpv_mul_set_vec64(mp_digit*, mp_digit *, mp_size, mp_digit);
|
||||
mp_digit MPI_ASM_DECL s_mpv_mul_add_vec64(mp_digit*, const mp_digit*, mp_size, mp_digit);
|
||||
|
||||
/* c = a * b */
|
||||
#define s_mpv_mul_d(a, a_len, b, c) \
|
||||
((unsigned long*)c)[a_len] = s_mpv_mul_set_vec64(c, a, a_len, b)
|
||||
|
||||
/* c += a * b */
|
||||
#define s_mpv_mul_d_add(a, a_len, b, c) \
|
||||
((unsigned long*)c)[a_len] = s_mpv_mul_add_vec64(c, a, a_len, b)
|
||||
|
||||
#else
|
||||
|
||||
void MPI_ASM_DECL s_mpv_mul_d(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c);
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c);
|
||||
|
||||
#endif
|
||||
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a,
|
||||
mp_size a_len, mp_digit b,
|
||||
mp_digit *c);
|
||||
void MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a,
|
||||
mp_size a_len,
|
||||
mp_digit *sqrs);
|
||||
|
||||
mp_err MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo,
|
||||
mp_digit divisor, mp_digit *quot, mp_digit *rem);
|
||||
|
||||
/* c += a * b * (MP_RADIX ** offset); */
|
||||
#define s_mp_mul_d_add_offset(a, b, c, off) \
|
||||
(s_mpv_mul_d_add_prop(MP_DIGITS(a), MP_USED(a), b, MP_DIGITS(c) + off), MP_OKAY)
|
||||
|
||||
typedef struct {
|
||||
mp_int N; /* modulus N */
|
||||
mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */
|
||||
mp_size b; /* R == 2 ** b, also b = # significant bits in N */
|
||||
} mp_mont_modulus;
|
||||
|
||||
mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
|
||||
mp_mont_modulus *mmm);
|
||||
mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm);
|
||||
|
||||
/*
|
||||
* s_mpi_getProcessorLineSize() returns the size in bytes of the cache line
|
||||
* if a cache exists, or zero if there is no cache. If more than one
|
||||
* cache line exists, it should return the smallest line size (which is
|
||||
* usually the L1 cache).
|
||||
*
|
||||
* mp_modexp uses this information to make sure that private key information
|
||||
* isn't being leaked through the cache.
|
||||
*
|
||||
* see mpcpucache.c for the implementation.
|
||||
*/
|
||||
unsigned long s_mpi_getProcessorLineSize();
|
||||
|
||||
/* }}} */
|
||||
#endif /* _MPI_PRIV_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,387 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* Arbitrary precision integer arithmetic library */
|
||||
|
||||
#ifndef _MPI_H
|
||||
#define _MPI_H
|
||||
|
||||
/* $Id: mpi.h,v 1.22 2004/04/27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#include "mpi-config.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/param.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/debug.h>
|
||||
#include <sys/systm.h>
|
||||
#define assert ASSERT
|
||||
#define labs(a) (a >= 0 ? a : -a)
|
||||
#define UCHAR_MAX 255
|
||||
#define memset(s, c, n) bzero(s, n)
|
||||
#define memcpy(a,b,c) bcopy((caddr_t)b, (caddr_t)a, c)
|
||||
/*
|
||||
* Generic #define's to cover missing things in the kernel
|
||||
*/
|
||||
#ifndef isdigit
|
||||
#define isdigit(x) ((x) >= '0' && (x) <= '9')
|
||||
#endif
|
||||
#ifndef isupper
|
||||
#define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z'))
|
||||
#endif
|
||||
#ifndef islower
|
||||
#define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z'))
|
||||
#endif
|
||||
#ifndef isalpha
|
||||
#define isalpha(x) (isupper(x) || islower(x))
|
||||
#endif
|
||||
#ifndef toupper
|
||||
#define toupper(x) (islower(x) ? (x) - 'a' + 'A' : (x))
|
||||
#endif
|
||||
#ifndef tolower
|
||||
#define tolower(x) (isupper(x) ? (x) + 'a' - 'A' : (x))
|
||||
#endif
|
||||
#ifndef isspace
|
||||
#define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \
|
||||
((x) == '\t') || ((x) == '\b'))
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#if MP_DEBUG
|
||||
#undef MP_IOFUNC
|
||||
#define MP_IOFUNC 1
|
||||
#endif
|
||||
|
||||
#if MP_IOFUNC
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined(BSDI)
|
||||
#undef ULLONG_MAX
|
||||
#endif
|
||||
|
||||
#if defined( macintosh )
|
||||
#include <Types.h>
|
||||
#elif defined( _WIN32_WCE)
|
||||
/* #include <sys/types.h> What do we need here ?? */
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define MP_NEG 1
|
||||
#define MP_ZPOS 0
|
||||
|
||||
#define MP_OKAY 0 /* no error, all is well */
|
||||
#define MP_YES 0 /* yes (boolean result) */
|
||||
#define MP_NO -1 /* no (boolean result) */
|
||||
#define MP_MEM -2 /* out of memory */
|
||||
#define MP_RANGE -3 /* argument out of range */
|
||||
#define MP_BADARG -4 /* invalid parameter */
|
||||
#define MP_UNDEF -5 /* answer is undefined */
|
||||
#define MP_LAST_CODE MP_UNDEF
|
||||
|
||||
typedef unsigned int mp_sign;
|
||||
typedef unsigned int mp_size;
|
||||
typedef int mp_err;
|
||||
typedef int mp_flag;
|
||||
|
||||
#define MP_32BIT_MAX 4294967295U
|
||||
|
||||
#if !defined(ULONG_MAX)
|
||||
#error "ULONG_MAX not defined"
|
||||
#elif !defined(UINT_MAX)
|
||||
#error "UINT_MAX not defined"
|
||||
#elif !defined(USHRT_MAX)
|
||||
#error "USHRT_MAX not defined"
|
||||
#endif
|
||||
|
||||
#if defined(ULONG_LONG_MAX) /* GCC, HPUX */
|
||||
#define MP_ULONG_LONG_MAX ULONG_LONG_MAX
|
||||
#elif defined(ULLONG_MAX) /* Solaris */
|
||||
#define MP_ULONG_LONG_MAX ULLONG_MAX
|
||||
/* MP_ULONG_LONG_MAX was defined to be ULLONG_MAX */
|
||||
#elif defined(ULONGLONG_MAX) /* IRIX, AIX */
|
||||
#define MP_ULONG_LONG_MAX ULONGLONG_MAX
|
||||
#endif
|
||||
|
||||
/* We only use unsigned long for mp_digit iff long is more than 32 bits. */
|
||||
#if !defined(MP_USE_UINT_DIGIT) && ULONG_MAX > MP_32BIT_MAX
|
||||
typedef unsigned long mp_digit;
|
||||
#define MP_DIGIT_MAX ULONG_MAX
|
||||
#define MP_DIGIT_FMT "%016lX" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX UINT_MAX
|
||||
#undef MP_NO_MP_WORD
|
||||
#define MP_NO_MP_WORD 1
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
#define MP_USE_LONG_DIGIT 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
|
||||
#elif !defined(MP_USE_UINT_DIGIT) && defined(MP_ULONG_LONG_MAX)
|
||||
typedef unsigned long long mp_digit;
|
||||
#define MP_DIGIT_MAX MP_ULONG_LONG_MAX
|
||||
#define MP_DIGIT_FMT "%016llX" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX UINT_MAX
|
||||
#undef MP_NO_MP_WORD
|
||||
#define MP_NO_MP_WORD 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
#define MP_USE_LONG_LONG_DIGIT 1
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
|
||||
#else
|
||||
typedef unsigned int mp_digit;
|
||||
#define MP_DIGIT_MAX UINT_MAX
|
||||
#define MP_DIGIT_FMT "%08X" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX USHRT_MAX
|
||||
#undef MP_USE_UINT_DIGIT
|
||||
#define MP_USE_UINT_DIGIT 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
#endif
|
||||
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
#if defined(MP_USE_UINT_DIGIT) && \
|
||||
(defined(MP_ULONG_LONG_MAX) || (ULONG_MAX > UINT_MAX))
|
||||
|
||||
#if (ULONG_MAX > UINT_MAX)
|
||||
typedef unsigned long mp_word;
|
||||
typedef long mp_sword;
|
||||
#define MP_WORD_MAX ULONG_MAX
|
||||
|
||||
#else
|
||||
typedef unsigned long long mp_word;
|
||||
typedef long long mp_sword;
|
||||
#define MP_WORD_MAX MP_ULONG_LONG_MAX
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define MP_NO_MP_WORD 1
|
||||
#endif
|
||||
#endif /* !defined(MP_NO_MP_WORD) */
|
||||
|
||||
#if !defined(MP_WORD_MAX) && defined(MP_DEFINE_SMALL_WORD)
|
||||
typedef unsigned int mp_word;
|
||||
typedef int mp_sword;
|
||||
#define MP_WORD_MAX UINT_MAX
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
|
||||
#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
|
||||
#define MP_RADIX (1+(mp_word)MP_DIGIT_MAX)
|
||||
|
||||
#define MP_HALF_DIGIT_BIT (MP_DIGIT_BIT/2)
|
||||
#define MP_HALF_RADIX (1+(mp_digit)MP_HALF_DIGIT_MAX)
|
||||
/* MP_HALF_RADIX really ought to be called MP_SQRT_RADIX, but it's named
|
||||
** MP_HALF_RADIX because it's the radix for MP_HALF_DIGITs, and it's
|
||||
** consistent with the other _HALF_ names.
|
||||
*/
|
||||
|
||||
|
||||
/* Macros for accessing the mp_int internals */
|
||||
#define MP_FLAG(MP) ((MP)->flag)
|
||||
#define MP_SIGN(MP) ((MP)->sign)
|
||||
#define MP_USED(MP) ((MP)->used)
|
||||
#define MP_ALLOC(MP) ((MP)->alloc)
|
||||
#define MP_DIGITS(MP) ((MP)->dp)
|
||||
#define MP_DIGIT(MP,N) (MP)->dp[(N)]
|
||||
|
||||
/* This defines the maximum I/O base (minimum is 2) */
|
||||
#define MP_MAX_RADIX 64
|
||||
|
||||
typedef struct {
|
||||
mp_sign flag; /* KM_SLEEP/KM_NOSLEEP */
|
||||
mp_sign sign; /* sign of this quantity */
|
||||
mp_size alloc; /* how many digits allocated */
|
||||
mp_size used; /* how many digits used */
|
||||
mp_digit *dp; /* the digits themselves */
|
||||
} mp_int;
|
||||
|
||||
/* Default precision */
|
||||
mp_size mp_get_prec(void);
|
||||
void mp_set_prec(mp_size prec);
|
||||
|
||||
/* Memory management */
|
||||
mp_err mp_init(mp_int *mp, int kmflag);
|
||||
mp_err mp_init_size(mp_int *mp, mp_size prec, int kmflag);
|
||||
mp_err mp_init_copy(mp_int *mp, const mp_int *from);
|
||||
mp_err mp_copy(const mp_int *from, mp_int *to);
|
||||
void mp_exch(mp_int *mp1, mp_int *mp2);
|
||||
void mp_clear(mp_int *mp);
|
||||
void mp_zero(mp_int *mp);
|
||||
void mp_set(mp_int *mp, mp_digit d);
|
||||
mp_err mp_set_int(mp_int *mp, long z);
|
||||
#define mp_set_long(mp,z) mp_set_int(mp,z)
|
||||
mp_err mp_set_ulong(mp_int *mp, unsigned long z);
|
||||
|
||||
/* Single digit arithmetic */
|
||||
mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_mul_2(const mp_int *a, mp_int *c);
|
||||
mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
|
||||
mp_err mp_div_2(const mp_int *a, mp_int *c);
|
||||
mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c);
|
||||
|
||||
/* Sign manipulations */
|
||||
mp_err mp_abs(const mp_int *a, mp_int *b);
|
||||
mp_err mp_neg(const mp_int *a, mp_int *b);
|
||||
|
||||
/* Full arithmetic */
|
||||
mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
#if MP_SQUARE
|
||||
mp_err mp_sqr(const mp_int *a, mp_int *b);
|
||||
#else
|
||||
#define mp_sqr(a, b) mp_mul(a, a, b)
|
||||
#endif
|
||||
mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r);
|
||||
mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r);
|
||||
mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_2expt(mp_int *a, mp_digit k);
|
||||
mp_err mp_sqrt(const mp_int *a, mp_int *b);
|
||||
|
||||
/* Modular arithmetic */
|
||||
#if MP_MODARITH
|
||||
mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c);
|
||||
mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
#if MP_SQUARE
|
||||
mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
#else
|
||||
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
|
||||
#endif
|
||||
mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c);
|
||||
#endif /* MP_MODARITH */
|
||||
|
||||
/* Comparisons */
|
||||
int mp_cmp_z(const mp_int *a);
|
||||
int mp_cmp_d(const mp_int *a, mp_digit d);
|
||||
int mp_cmp(const mp_int *a, const mp_int *b);
|
||||
int mp_cmp_mag(mp_int *a, mp_int *b);
|
||||
int mp_cmp_int(const mp_int *a, long z, int kmflag);
|
||||
int mp_isodd(const mp_int *a);
|
||||
int mp_iseven(const mp_int *a);
|
||||
|
||||
/* Number theoretic */
|
||||
#if MP_NUMTH
|
||||
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
|
||||
mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
#endif /* end MP_NUMTH */
|
||||
|
||||
/* Input and output */
|
||||
#if MP_IOFUNC
|
||||
void mp_print(mp_int *mp, FILE *ofp);
|
||||
#endif /* end MP_IOFUNC */
|
||||
|
||||
/* Base conversion */
|
||||
mp_err mp_read_raw(mp_int *mp, char *str, int len);
|
||||
int mp_raw_size(mp_int *mp);
|
||||
mp_err mp_toraw(mp_int *mp, char *str);
|
||||
mp_err mp_read_radix(mp_int *mp, const char *str, int radix);
|
||||
mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix);
|
||||
int mp_radix_size(mp_int *mp, int radix);
|
||||
mp_err mp_toradix(mp_int *mp, char *str, int radix);
|
||||
int mp_tovalue(char ch, int r);
|
||||
|
||||
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
|
||||
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
|
||||
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
|
||||
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
|
||||
|
||||
/* Error strings */
|
||||
const char *mp_strerror(mp_err ec);
|
||||
|
||||
/* Octet string conversion functions */
|
||||
mp_err mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len);
|
||||
int mp_unsigned_octet_size(const mp_int *mp);
|
||||
mp_err mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
|
||||
mp_err mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
|
||||
mp_err mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size len);
|
||||
|
||||
/* Miscellaneous */
|
||||
mp_size mp_trailing_zeros(const mp_int *mp);
|
||||
|
||||
#define MP_CHECKOK(x) if (MP_OKAY > (res = (x))) goto CLEANUP
|
||||
#define MP_CHECKERR(x) if (MP_OKAY > (res = (x))) goto CLEANUP
|
||||
|
||||
#if defined(MP_API_COMPATIBLE)
|
||||
#define NEG MP_NEG
|
||||
#define ZPOS MP_ZPOS
|
||||
#define DIGIT_MAX MP_DIGIT_MAX
|
||||
#define DIGIT_BIT MP_DIGIT_BIT
|
||||
#define DIGIT_FMT MP_DIGIT_FMT
|
||||
#define RADIX MP_RADIX
|
||||
#define MAX_RADIX MP_MAX_RADIX
|
||||
#define FLAG(MP) MP_FLAG(MP)
|
||||
#define SIGN(MP) MP_SIGN(MP)
|
||||
#define USED(MP) MP_USED(MP)
|
||||
#define ALLOC(MP) MP_ALLOC(MP)
|
||||
#define DIGITS(MP) MP_DIGITS(MP)
|
||||
#define DIGIT(MP,N) MP_DIGIT(MP,N)
|
||||
|
||||
#if MP_ARGCHK == 1
|
||||
#define ARGCHK(X,Y) {if(!(X)){return (Y);}}
|
||||
#elif MP_ARGCHK == 2
|
||||
#ifdef _KERNEL
|
||||
#define ARGCHK(X,Y) ASSERT(X)
|
||||
#else
|
||||
#include <assert.h>
|
||||
#define ARGCHK(X,Y) assert(X)
|
||||
#endif
|
||||
#else
|
||||
#define ARGCHK(X,Y) /* */
|
||||
#endif
|
||||
#endif /* defined MP_API_COMPATIBLE */
|
||||
|
||||
#endif /* _MPI_H */
|
@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* Bitwise logical operations on MPI values */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* {{{ Lookup table for population count */
|
||||
|
||||
static unsigned char bitc[] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
mpl_rsh(a, b, d) - b = a >> d
|
||||
mpl_lsh(a, b, d) - b = a << d
|
||||
*/
|
||||
|
||||
/* {{{ mpl_rsh(a, b, d) */
|
||||
|
||||
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
s_mp_div_2d(b, d);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_rsh() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_lsh(a, b, d) */
|
||||
|
||||
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
return s_mp_mul_2d(b, d);
|
||||
|
||||
} /* end mpl_lsh() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_set_bit
|
||||
|
||||
Returns MP_OKAY or some error code.
|
||||
Grows a if needed to set a bit to 1.
|
||||
*/
|
||||
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
|
||||
{
|
||||
mp_size ix;
|
||||
mp_err rv;
|
||||
mp_digit mask;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = bitNum / MP_DIGIT_BIT;
|
||||
if (ix + 1 > MP_USED(a)) {
|
||||
rv = s_mp_pad(a, ix + 1);
|
||||
if (rv != MP_OKAY)
|
||||
return rv;
|
||||
}
|
||||
|
||||
bitNum = bitNum % MP_DIGIT_BIT;
|
||||
mask = (mp_digit)1 << bitNum;
|
||||
if (value)
|
||||
MP_DIGIT(a,ix) |= mask;
|
||||
else
|
||||
MP_DIGIT(a,ix) &= ~mask;
|
||||
s_mp_clamp(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_get_bit
|
||||
|
||||
returns 0 or 1 or some (negative) error code.
|
||||
*/
|
||||
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum)
|
||||
{
|
||||
mp_size bit, ix;
|
||||
mp_err rv;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = bitNum / MP_DIGIT_BIT;
|
||||
ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);
|
||||
|
||||
bit = bitNum % MP_DIGIT_BIT;
|
||||
rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_get_bits
|
||||
- Extracts numBits bits from a, where the least significant extracted bit
|
||||
is bit lsbNum. Returns a negative value if error occurs.
|
||||
- Because sign bit is used to indicate error, maximum number of bits to
|
||||
be returned is the lesser of (a) the number of bits in an mp_digit, or
|
||||
(b) one less than the number of bits in an mp_err.
|
||||
- lsbNum + numbits can be greater than the number of significant bits in
|
||||
integer a, as long as bit lsbNum is in the high order digit of a.
|
||||
*/
|
||||
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
|
||||
{
|
||||
mp_size rshift = (lsbNum % MP_DIGIT_BIT);
|
||||
mp_size lsWndx = (lsbNum / MP_DIGIT_BIT);
|
||||
mp_digit * digit = MP_DIGITS(a) + lsWndx;
|
||||
mp_digit mask = ((1 << numBits) - 1);
|
||||
|
||||
ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
|
||||
ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);
|
||||
|
||||
if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
|
||||
(lsWndx + 1 >= MP_USED(a))) {
|
||||
mask &= (digit[0] >> rshift);
|
||||
} else {
|
||||
mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
|
||||
}
|
||||
return (mp_err)mask;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_significant_bits
|
||||
returns number of significnant bits in abs(a).
|
||||
returns 1 if value is zero.
|
||||
*/
|
||||
mp_err mpl_significant_bits(const mp_int *a)
|
||||
{
|
||||
mp_err bits = 0;
|
||||
int ix;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = MP_USED(a);
|
||||
for (ix = MP_USED(a); ix > 0; ) {
|
||||
mp_digit d;
|
||||
d = MP_DIGIT(a, --ix);
|
||||
if (d) {
|
||||
while (d) {
|
||||
++bits;
|
||||
d >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
bits += ix * MP_DIGIT_BIT;
|
||||
if (!bits)
|
||||
bits = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* HERE THERE BE DRAGONS */
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* Bitwise logical operations on MPI values */
|
||||
|
||||
#ifndef _MPLOGIC_H
|
||||
#define _MPLOGIC_H
|
||||
|
||||
/* $Id: mplogic.h,v 1.7 2004/04/27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
/*
|
||||
The logical operations treat an mp_int as if it were a bit vector,
|
||||
without regard to its sign (an mp_int is represented in a signed
|
||||
magnitude format). Values are treated as if they had an infinite
|
||||
string of zeros left of the most-significant bit.
|
||||
*/
|
||||
|
||||
/* Parity results */
|
||||
|
||||
#define MP_EVEN MP_YES
|
||||
#define MP_ODD MP_NO
|
||||
|
||||
/* Bitwise functions */
|
||||
|
||||
mp_err mpl_not(mp_int *a, mp_int *b); /* one's complement */
|
||||
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c); /* bitwise AND */
|
||||
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c); /* bitwise OR */
|
||||
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c); /* bitwise XOR */
|
||||
|
||||
/* Shift functions */
|
||||
|
||||
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d); /* right shift */
|
||||
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d); /* left shift */
|
||||
|
||||
/* Bit count and parity */
|
||||
|
||||
mp_err mpl_num_set(mp_int *a, int *num); /* count set bits */
|
||||
mp_err mpl_num_clear(mp_int *a, int *num); /* count clear bits */
|
||||
mp_err mpl_parity(mp_int *a); /* determine parity */
|
||||
|
||||
/* Get & Set the value of a bit */
|
||||
|
||||
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value);
|
||||
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum);
|
||||
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits);
|
||||
mp_err mpl_significant_bits(const mp_int *a);
|
||||
|
||||
#endif /* _MPLOGIC_H */
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <stephen.fung@sun.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* This file implements moduluar exponentiation using Montgomery's
|
||||
* method for modular reduction. This file implements the method
|
||||
* described as "Improvement 1" in the paper "A Cryptogrpahic Library for
|
||||
* the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr.
|
||||
* published in "Advances in Cryptology: Proceedings of EUROCRYPT '90"
|
||||
* "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244,
|
||||
* published by Springer Verlag.
|
||||
*/
|
||||
|
||||
#define MP_USING_CACHE_SAFE_MOD_EXP 1
|
||||
#ifndef _KERNEL
|
||||
#include <string.h>
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#endif
|
||||
#include "mpi-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpprime.h"
|
||||
#ifdef MP_USING_MONT_MULF
|
||||
#include "montmulf.h"
|
||||
#endif
|
||||
|
||||
/* if MP_CHAR_STORE_SLOW is defined, we */
|
||||
/* need to know endianness of this platform. */
|
||||
#ifdef MP_CHAR_STORE_SLOW
|
||||
#if !defined(MP_IS_BIG_ENDIAN) && !defined(MP_IS_LITTLE_ENDIAN)
|
||||
#error "You must define MP_IS_BIG_ENDIAN or MP_IS_LITTLE_ENDIAN\n" \
|
||||
" if you define MP_CHAR_STORE_SLOW."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef STATIC
|
||||
#define STATIC
|
||||
#endif
|
||||
|
||||
#define MAX_ODD_INTS 32 /* 2 ** (WINDOW_BITS - 1) */
|
||||
|
||||
#ifndef _KERNEL
|
||||
#if defined(_WIN32_WCE)
|
||||
#define ABORT res = MP_UNDEF; goto CLEANUP
|
||||
#else
|
||||
#define ABORT abort()
|
||||
#endif
|
||||
#else
|
||||
#define ABORT res = MP_UNDEF; goto CLEANUP
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/* computes T = REDC(T), 2^b == R */
|
||||
mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm)
|
||||
{
|
||||
mp_err res;
|
||||
mp_size i;
|
||||
|
||||
i = MP_USED(T) + MP_USED(&mmm->N) + 2;
|
||||
MP_CHECKOK( s_mp_pad(T, i) );
|
||||
for (i = 0; i < MP_USED(&mmm->N); ++i ) {
|
||||
mp_digit m_i = MP_DIGIT(T, i) * mmm->n0prime;
|
||||
/* T += N * m_i * (MP_RADIX ** i); */
|
||||
MP_CHECKOK( s_mp_mul_d_add_offset(&mmm->N, m_i, T, i) );
|
||||
}
|
||||
s_mp_clamp(T);
|
||||
|
||||
/* T /= R */
|
||||
s_mp_div_2d(T, mmm->b);
|
||||
|
||||
if ((res = s_mp_cmp(T, &mmm->N)) >= 0) {
|
||||
/* T = T - N */
|
||||
MP_CHECKOK( s_mp_sub(T, &mmm->N) );
|
||||
#ifdef DEBUG
|
||||
if ((res = mp_cmp(T, &mmm->N)) >= 0) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
res = MP_OKAY;
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !defined(MP_ASSEMBLY_MUL_MONT) && !defined(MP_MONT_USE_MP_MUL)
|
||||
mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
|
||||
mp_mont_modulus *mmm)
|
||||
{
|
||||
mp_digit *pb;
|
||||
mp_digit m_i;
|
||||
mp_err res;
|
||||
mp_size ib;
|
||||
mp_size useda, usedb;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (MP_USED(a) < MP_USED(b)) {
|
||||
const mp_int *xch = b; /* switch a and b, to do fewer outer loops */
|
||||
b = a;
|
||||
a = xch;
|
||||
}
|
||||
|
||||
MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
|
||||
ib = MP_USED(a) + MP_MAX(MP_USED(b), MP_USED(&mmm->N)) + 2;
|
||||
if((res = s_mp_pad(c, ib)) != MP_OKAY)
|
||||
goto CLEANUP;
|
||||
|
||||
useda = MP_USED(a);
|
||||
pb = MP_DIGITS(b);
|
||||
s_mpv_mul_d(MP_DIGITS(a), useda, *pb++, MP_DIGITS(c));
|
||||
s_mp_setz(MP_DIGITS(c) + useda + 1, ib - (useda + 1));
|
||||
m_i = MP_DIGIT(c, 0) * mmm->n0prime;
|
||||
s_mp_mul_d_add_offset(&mmm->N, m_i, c, 0);
|
||||
|
||||
/* Outer loop: Digits of b */
|
||||
usedb = MP_USED(b);
|
||||
for (ib = 1; ib < usedb; ib++) {
|
||||
mp_digit b_i = *pb++;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
if (b_i)
|
||||
s_mpv_mul_d_add_prop(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
|
||||
m_i = MP_DIGIT(c, ib) * mmm->n0prime;
|
||||
s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
|
||||
}
|
||||
if (usedb < MP_USED(&mmm->N)) {
|
||||
for (usedb = MP_USED(&mmm->N); ib < usedb; ++ib ) {
|
||||
m_i = MP_DIGIT(c, ib) * mmm->n0prime;
|
||||
s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
|
||||
}
|
||||
}
|
||||
s_mp_clamp(c);
|
||||
s_mp_div_2d(c, mmm->b);
|
||||
if (s_mp_cmp(c, &mmm->N) >= 0) {
|
||||
MP_CHECKOK( s_mp_sub(c, &mmm->N) );
|
||||
}
|
||||
res = MP_OKAY;
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
#endif
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1997
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
/* Utilities for finding and working with prime and pseudo-prime integers */
|
||||
|
||||
#ifndef _MP_PRIME_H
|
||||
#define _MP_PRIME_H
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
extern const int prime_tab_size; /* number of primes available */
|
||||
extern const mp_digit prime_tab[];
|
||||
|
||||
/* Tests for divisibility */
|
||||
mp_err mpp_divis(mp_int *a, mp_int *b);
|
||||
mp_err mpp_divis_d(mp_int *a, mp_digit d);
|
||||
|
||||
/* Random selection */
|
||||
mp_err mpp_random(mp_int *a);
|
||||
mp_err mpp_random_size(mp_int *a, mp_size prec);
|
||||
|
||||
/* Pseudo-primality testing */
|
||||
mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which);
|
||||
mp_err mpp_divis_primes(mp_int *a, mp_digit *np);
|
||||
mp_err mpp_fermat(mp_int *a, mp_digit w);
|
||||
mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes);
|
||||
mp_err mpp_pprime(mp_int *a, int nt);
|
||||
mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
|
||||
unsigned char *sieve, mp_size nSieve);
|
||||
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
|
||||
unsigned long * nTries);
|
||||
|
||||
#endif /* _MP_PRIME_H */
|
@ -1,538 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Last Modified Date from the Original Code: March 2012
|
||||
*********************************************************************** */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#if !defined(__linux__) && !defined(_ALLBSD_SOURCE)
|
||||
#include <sys/systm.h>
|
||||
#endif /* __linux__ || _ALLBSD_SOURCE */
|
||||
#include <sys/param.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/kmem.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include "ec.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecc_impl.h"
|
||||
#include "secoidt.h"
|
||||
|
||||
#define CERTICOM_OID 0x2b, 0x81, 0x04
|
||||
#define SECG_OID CERTICOM_OID, 0x00
|
||||
|
||||
#define ANSI_X962_OID 0x2a, 0x86, 0x48, 0xce, 0x3d
|
||||
#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03
|
||||
#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
|
||||
#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01
|
||||
|
||||
#define TELETRUST_ALGO_OID 0x2b, 0x24, 0x03
|
||||
#define ECC_BRAINPOOL TELETRUST_ALGO_OID, 0x03, 0x02, 0x08
|
||||
#define ECC_BRAINPOOL_EC_V1 ECC_BRAINPOOL, 0x01, 0x01
|
||||
|
||||
#define CONST_OID static const unsigned char
|
||||
|
||||
/* ANSI X9.62 prime curve OIDs */
|
||||
/* NOTE: prime192v1 is the same as secp192r1, prime256v1 is the
|
||||
* same as secp256r1
|
||||
*/
|
||||
CONST_OID ansiX962prime192v1[] = { ANSI_X962_GFp_OID, 0x01 };
|
||||
CONST_OID ansiX962prime192v2[] = { ANSI_X962_GFp_OID, 0x02 };
|
||||
CONST_OID ansiX962prime192v3[] = { ANSI_X962_GFp_OID, 0x03 };
|
||||
CONST_OID ansiX962prime239v1[] = { ANSI_X962_GFp_OID, 0x04 };
|
||||
CONST_OID ansiX962prime239v2[] = { ANSI_X962_GFp_OID, 0x05 };
|
||||
CONST_OID ansiX962prime239v3[] = { ANSI_X962_GFp_OID, 0x06 };
|
||||
CONST_OID ansiX962prime256v1[] = { ANSI_X962_GFp_OID, 0x07 };
|
||||
|
||||
/* SECG prime curve OIDs */
|
||||
CONST_OID secgECsecp112r1[] = { SECG_OID, 0x06 };
|
||||
CONST_OID secgECsecp112r2[] = { SECG_OID, 0x07 };
|
||||
CONST_OID secgECsecp128r1[] = { SECG_OID, 0x1c };
|
||||
CONST_OID secgECsecp128r2[] = { SECG_OID, 0x1d };
|
||||
CONST_OID secgECsecp160k1[] = { SECG_OID, 0x09 };
|
||||
CONST_OID secgECsecp160r1[] = { SECG_OID, 0x08 };
|
||||
CONST_OID secgECsecp160r2[] = { SECG_OID, 0x1e };
|
||||
CONST_OID secgECsecp192k1[] = { SECG_OID, 0x1f };
|
||||
CONST_OID secgECsecp224k1[] = { SECG_OID, 0x20 };
|
||||
CONST_OID secgECsecp224r1[] = { SECG_OID, 0x21 };
|
||||
CONST_OID secgECsecp256k1[] = { SECG_OID, 0x0a };
|
||||
CONST_OID secgECsecp384r1[] = { SECG_OID, 0x22 };
|
||||
CONST_OID secgECsecp521r1[] = { SECG_OID, 0x23 };
|
||||
|
||||
/* SECG characterisitic two curve OIDs */
|
||||
CONST_OID secgECsect113r1[] = {SECG_OID, 0x04 };
|
||||
CONST_OID secgECsect113r2[] = {SECG_OID, 0x05 };
|
||||
CONST_OID secgECsect131r1[] = {SECG_OID, 0x16 };
|
||||
CONST_OID secgECsect131r2[] = {SECG_OID, 0x17 };
|
||||
CONST_OID secgECsect163k1[] = {SECG_OID, 0x01 };
|
||||
CONST_OID secgECsect163r1[] = {SECG_OID, 0x02 };
|
||||
CONST_OID secgECsect163r2[] = {SECG_OID, 0x0f };
|
||||
CONST_OID secgECsect193r1[] = {SECG_OID, 0x18 };
|
||||
CONST_OID secgECsect193r2[] = {SECG_OID, 0x19 };
|
||||
CONST_OID secgECsect233k1[] = {SECG_OID, 0x1a };
|
||||
CONST_OID secgECsect233r1[] = {SECG_OID, 0x1b };
|
||||
CONST_OID secgECsect239k1[] = {SECG_OID, 0x03 };
|
||||
CONST_OID secgECsect283k1[] = {SECG_OID, 0x10 };
|
||||
CONST_OID secgECsect283r1[] = {SECG_OID, 0x11 };
|
||||
CONST_OID secgECsect409k1[] = {SECG_OID, 0x24 };
|
||||
CONST_OID secgECsect409r1[] = {SECG_OID, 0x25 };
|
||||
CONST_OID secgECsect571k1[] = {SECG_OID, 0x26 };
|
||||
CONST_OID secgECsect571r1[] = {SECG_OID, 0x27 };
|
||||
|
||||
/* ANSI X9.62 characteristic two curve OIDs */
|
||||
CONST_OID ansiX962c2pnb163v1[] = { ANSI_X962_GF2m_OID, 0x01 };
|
||||
CONST_OID ansiX962c2pnb163v2[] = { ANSI_X962_GF2m_OID, 0x02 };
|
||||
CONST_OID ansiX962c2pnb163v3[] = { ANSI_X962_GF2m_OID, 0x03 };
|
||||
CONST_OID ansiX962c2pnb176v1[] = { ANSI_X962_GF2m_OID, 0x04 };
|
||||
CONST_OID ansiX962c2tnb191v1[] = { ANSI_X962_GF2m_OID, 0x05 };
|
||||
CONST_OID ansiX962c2tnb191v2[] = { ANSI_X962_GF2m_OID, 0x06 };
|
||||
CONST_OID ansiX962c2tnb191v3[] = { ANSI_X962_GF2m_OID, 0x07 };
|
||||
CONST_OID ansiX962c2onb191v4[] = { ANSI_X962_GF2m_OID, 0x08 };
|
||||
CONST_OID ansiX962c2onb191v5[] = { ANSI_X962_GF2m_OID, 0x09 };
|
||||
CONST_OID ansiX962c2pnb208w1[] = { ANSI_X962_GF2m_OID, 0x0a };
|
||||
CONST_OID ansiX962c2tnb239v1[] = { ANSI_X962_GF2m_OID, 0x0b };
|
||||
CONST_OID ansiX962c2tnb239v2[] = { ANSI_X962_GF2m_OID, 0x0c };
|
||||
CONST_OID ansiX962c2tnb239v3[] = { ANSI_X962_GF2m_OID, 0x0d };
|
||||
CONST_OID ansiX962c2onb239v4[] = { ANSI_X962_GF2m_OID, 0x0e };
|
||||
CONST_OID ansiX962c2onb239v5[] = { ANSI_X962_GF2m_OID, 0x0f };
|
||||
CONST_OID ansiX962c2pnb272w1[] = { ANSI_X962_GF2m_OID, 0x10 };
|
||||
CONST_OID ansiX962c2pnb304w1[] = { ANSI_X962_GF2m_OID, 0x11 };
|
||||
CONST_OID ansiX962c2tnb359v1[] = { ANSI_X962_GF2m_OID, 0x12 };
|
||||
CONST_OID ansiX962c2pnb368w1[] = { ANSI_X962_GF2m_OID, 0x13 };
|
||||
CONST_OID ansiX962c2tnb431r1[] = { ANSI_X962_GF2m_OID, 0x14 };
|
||||
|
||||
/* TeleTrusT ECC Brainpool prime curve OIDs */
|
||||
CONST_OID brainpoolP160r1[] = { ECC_BRAINPOOL_EC_V1, 0x01 };
|
||||
CONST_OID brainpoolP160t1[] = { ECC_BRAINPOOL_EC_V1, 0x02 };
|
||||
CONST_OID brainpoolP192r1[] = { ECC_BRAINPOOL_EC_V1, 0x03 };
|
||||
CONST_OID brainpoolP192t1[] = { ECC_BRAINPOOL_EC_V1, 0x04 };
|
||||
CONST_OID brainpoolP224r1[] = { ECC_BRAINPOOL_EC_V1, 0x05 };
|
||||
CONST_OID brainpoolP224t1[] = { ECC_BRAINPOOL_EC_V1, 0x06 };
|
||||
CONST_OID brainpoolP256r1[] = { ECC_BRAINPOOL_EC_V1, 0x07 };
|
||||
CONST_OID brainpoolP256t1[] = { ECC_BRAINPOOL_EC_V1, 0x08 };
|
||||
CONST_OID brainpoolP320r1[] = { ECC_BRAINPOOL_EC_V1, 0x09 };
|
||||
CONST_OID brainpoolP320t1[] = { ECC_BRAINPOOL_EC_V1, 0x0a };
|
||||
CONST_OID brainpoolP384r1[] = { ECC_BRAINPOOL_EC_V1, 0x0b };
|
||||
CONST_OID brainpoolP384t1[] = { ECC_BRAINPOOL_EC_V1, 0x0c };
|
||||
CONST_OID brainpoolP512r1[] = { ECC_BRAINPOOL_EC_V1, 0x0d };
|
||||
CONST_OID brainpoolP512t1[] = { ECC_BRAINPOOL_EC_V1, 0x0e };
|
||||
|
||||
#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
|
||||
#ifndef SECOID_NO_STRINGS
|
||||
#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
|
||||
#else
|
||||
#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, 0, mech, ext }
|
||||
#endif
|
||||
|
||||
#define CKM_INVALID_MECHANISM 0xffffffffUL
|
||||
|
||||
/* XXX this is incorrect */
|
||||
#define INVALID_CERT_EXTENSION 1
|
||||
|
||||
#define CKM_ECDSA 0x00001041
|
||||
#define CKM_ECDSA_SHA1 0x00001042
|
||||
#define CKM_ECDH1_DERIVE 0x00001050
|
||||
|
||||
static SECOidData ANSI_prime_oids[] = {
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
|
||||
OD( ansiX962prime192v1, ECCurve_NIST_P192,
|
||||
"ANSI X9.62 elliptic curve prime192v1 (aka secp192r1, NIST P-192)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962prime192v2, ECCurve_X9_62_PRIME_192V2,
|
||||
"ANSI X9.62 elliptic curve prime192v2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962prime192v3, ECCurve_X9_62_PRIME_192V3,
|
||||
"ANSI X9.62 elliptic curve prime192v3",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962prime239v1, ECCurve_X9_62_PRIME_239V1,
|
||||
"ANSI X9.62 elliptic curve prime239v1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962prime239v2, ECCurve_X9_62_PRIME_239V2,
|
||||
"ANSI X9.62 elliptic curve prime239v2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962prime239v3, ECCurve_X9_62_PRIME_239V3,
|
||||
"ANSI X9.62 elliptic curve prime239v3",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962prime256v1, ECCurve_NIST_P256,
|
||||
"ANSI X9.62 elliptic curve prime256v1 (aka secp256r1, NIST P-256)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION )
|
||||
};
|
||||
|
||||
static SECOidData SECG_oids[] = {
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
|
||||
OD( secgECsect163k1, ECCurve_NIST_K163,
|
||||
"SECG elliptic curve sect163k1 (aka NIST K-163)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect163r1, ECCurve_SECG_CHAR2_163R1,
|
||||
"SECG elliptic curve sect163r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect239k1, ECCurve_SECG_CHAR2_239K1,
|
||||
"SECG elliptic curve sect239k1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect113r1, ECCurve_SECG_CHAR2_113R1,
|
||||
"SECG elliptic curve sect113r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect113r2, ECCurve_SECG_CHAR2_113R2,
|
||||
"SECG elliptic curve sect113r2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp112r1, ECCurve_SECG_PRIME_112R1,
|
||||
"SECG elliptic curve secp112r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp112r2, ECCurve_SECG_PRIME_112R2,
|
||||
"SECG elliptic curve secp112r2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp160r1, ECCurve_SECG_PRIME_160R1,
|
||||
"SECG elliptic curve secp160r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp160k1, ECCurve_SECG_PRIME_160K1,
|
||||
"SECG elliptic curve secp160k1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp256k1, ECCurve_SECG_PRIME_256K1,
|
||||
"SECG elliptic curve secp256k1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( secgECsect163r2, ECCurve_NIST_B163,
|
||||
"SECG elliptic curve sect163r2 (aka NIST B-163)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect283k1, ECCurve_NIST_K283,
|
||||
"SECG elliptic curve sect283k1 (aka NIST K-283)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect283r1, ECCurve_NIST_B283,
|
||||
"SECG elliptic curve sect283r1 (aka NIST B-283)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( secgECsect131r1, ECCurve_SECG_CHAR2_131R1,
|
||||
"SECG elliptic curve sect131r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect131r2, ECCurve_SECG_CHAR2_131R2,
|
||||
"SECG elliptic curve sect131r2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect193r1, ECCurve_SECG_CHAR2_193R1,
|
||||
"SECG elliptic curve sect193r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect193r2, ECCurve_SECG_CHAR2_193R2,
|
||||
"SECG elliptic curve sect193r2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect233k1, ECCurve_NIST_K233,
|
||||
"SECG elliptic curve sect233k1 (aka NIST K-233)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect233r1, ECCurve_NIST_B233,
|
||||
"SECG elliptic curve sect233r1 (aka NIST B-233)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp128r1, ECCurve_SECG_PRIME_128R1,
|
||||
"SECG elliptic curve secp128r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp128r2, ECCurve_SECG_PRIME_128R2,
|
||||
"SECG elliptic curve secp128r2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp160r2, ECCurve_SECG_PRIME_160R2,
|
||||
"SECG elliptic curve secp160r2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp192k1, ECCurve_SECG_PRIME_192K1,
|
||||
"SECG elliptic curve secp192k1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp224k1, ECCurve_SECG_PRIME_224K1,
|
||||
"SECG elliptic curve secp224k1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp224r1, ECCurve_NIST_P224,
|
||||
"SECG elliptic curve secp224r1 (aka NIST P-224)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp384r1, ECCurve_NIST_P384,
|
||||
"SECG elliptic curve secp384r1 (aka NIST P-384)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsecp521r1, ECCurve_NIST_P521,
|
||||
"SECG elliptic curve secp521r1 (aka NIST P-521)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect409k1, ECCurve_NIST_K409,
|
||||
"SECG elliptic curve sect409k1 (aka NIST K-409)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect409r1, ECCurve_NIST_B409,
|
||||
"SECG elliptic curve sect409r1 (aka NIST B-409)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect571k1, ECCurve_NIST_K571,
|
||||
"SECG elliptic curve sect571k1 (aka NIST K-571)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( secgECsect571r1, ECCurve_NIST_B571,
|
||||
"SECG elliptic curve sect571r1 (aka NIST B-571)",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION )
|
||||
};
|
||||
|
||||
static SECOidData ANSI_oids[] = {
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
|
||||
/* ANSI X9.62 named elliptic curves (characteristic two field) */
|
||||
OD( ansiX962c2pnb163v1, ECCurve_X9_62_CHAR2_PNB163V1,
|
||||
"ANSI X9.62 elliptic curve c2pnb163v1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2pnb163v2, ECCurve_X9_62_CHAR2_PNB163V2,
|
||||
"ANSI X9.62 elliptic curve c2pnb163v2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2pnb163v3, ECCurve_X9_62_CHAR2_PNB163V3,
|
||||
"ANSI X9.62 elliptic curve c2pnb163v3",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2pnb176v1, ECCurve_X9_62_CHAR2_PNB176V1,
|
||||
"ANSI X9.62 elliptic curve c2pnb176v1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb191v1, ECCurve_X9_62_CHAR2_TNB191V1,
|
||||
"ANSI X9.62 elliptic curve c2tnb191v1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb191v2, ECCurve_X9_62_CHAR2_TNB191V2,
|
||||
"ANSI X9.62 elliptic curve c2tnb191v2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb191v3, ECCurve_X9_62_CHAR2_TNB191V3,
|
||||
"ANSI X9.62 elliptic curve c2tnb191v3",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( ansiX962c2pnb208w1, ECCurve_X9_62_CHAR2_PNB208W1,
|
||||
"ANSI X9.62 elliptic curve c2pnb208w1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb239v1, ECCurve_X9_62_CHAR2_TNB239V1,
|
||||
"ANSI X9.62 elliptic curve c2tnb239v1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb239v2, ECCurve_X9_62_CHAR2_TNB239V2,
|
||||
"ANSI X9.62 elliptic curve c2tnb239v2",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb239v3, ECCurve_X9_62_CHAR2_TNB239V3,
|
||||
"ANSI X9.62 elliptic curve c2tnb239v3",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( ansiX962c2pnb272w1, ECCurve_X9_62_CHAR2_PNB272W1,
|
||||
"ANSI X9.62 elliptic curve c2pnb272w1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2pnb304w1, ECCurve_X9_62_CHAR2_PNB304W1,
|
||||
"ANSI X9.62 elliptic curve c2pnb304w1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb359v1, ECCurve_X9_62_CHAR2_TNB359V1,
|
||||
"ANSI X9.62 elliptic curve c2tnb359v1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2pnb368w1, ECCurve_X9_62_CHAR2_PNB368W1,
|
||||
"ANSI X9.62 elliptic curve c2pnb368w1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
OD( ansiX962c2tnb431r1, ECCurve_X9_62_CHAR2_TNB431R1,
|
||||
"ANSI X9.62 elliptic curve c2tnb431r1",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION )
|
||||
};
|
||||
|
||||
static SECOidData BRAINPOOL_oids[] = {
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
|
||||
/* RFC 5639 Brainpool named elliptic curves */
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( brainpoolP256r1, ECCurve_BrainpoolP256r1,
|
||||
"brainpoolP256r1 domain parameter set",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( brainpoolP320r1, ECCurve_BrainpoolP320r1,
|
||||
"brainpoolP320r1 domain parameter set",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( brainpoolP384r1, ECCurve_BrainpoolP384r1,
|
||||
"brainpoolP384r1 domain parameter set",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
|
||||
OD( brainpoolP512r1, ECCurve_BrainpoolP512r1,
|
||||
"brainpoolP512r1 domain parameter set",
|
||||
CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION ),
|
||||
{ { siDEROID, NULL, 0 }, ECCurve_noName,
|
||||
"Unknown OID", CKM_INVALID_MECHANISM,
|
||||
INVALID_CERT_EXTENSION }
|
||||
};
|
||||
|
||||
int
|
||||
oideql(unsigned char *reqoid, unsigned char *foundoid, size_t reqlen, size_t foundlen)
|
||||
{
|
||||
if (!reqoid || !foundoid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reqlen != foundlen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return memcmp(reqoid, foundoid, reqlen) == 0;
|
||||
}
|
||||
|
||||
SECOidData *
|
||||
SECOID_FindOID(const SECItem *oid)
|
||||
{
|
||||
SECOidData *po;
|
||||
SECOidData *ret = NULL;
|
||||
int reqlen = oid->len;
|
||||
|
||||
if (reqlen == 8) {
|
||||
if (oid->data[6] == 0x00) {
|
||||
/* XXX bounds check */
|
||||
po = &ANSI_oids[oid->data[7]];
|
||||
if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
|
||||
ret = po;
|
||||
}
|
||||
}
|
||||
if (oid->data[6] == 0x01) {
|
||||
/* XXX bounds check */
|
||||
po = &ANSI_prime_oids[oid->data[7]];
|
||||
if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
|
||||
ret = po;
|
||||
}
|
||||
}
|
||||
} else if (reqlen == 5) {
|
||||
/* XXX bounds check */
|
||||
po = &SECG_oids[oid->data[4]];
|
||||
if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
|
||||
ret = po;
|
||||
}
|
||||
} else if (reqlen == 9) {
|
||||
/* XXX bounds check */
|
||||
po = &BRAINPOOL_oids[oid->data[8]];
|
||||
if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
|
||||
ret = po;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
ECCurveName
|
||||
SECOID_FindOIDTag(const SECItem *oid)
|
||||
{
|
||||
SECOidData *oiddata;
|
||||
|
||||
oiddata = SECOID_FindOID (oid);
|
||||
if (oiddata == NULL)
|
||||
return ECCurve_noName;
|
||||
|
||||
return oiddata->offset;
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Last Modified Date from the Original Code: March 2012
|
||||
*********************************************************************** */
|
||||
|
||||
/*
|
||||
* Support routines for SECItem data structure.
|
||||
*
|
||||
* $Id: secitem.c,v 1.14 2006/05/22 22:24:34 wtchang%redhat.com Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#if !defined(__linux__) && !defined(_ALLBSD_SOURCE)
|
||||
#include <sys/systm.h>
|
||||
#endif /* __linux__ || _ALLBSD_SOURCE */
|
||||
#include <sys/param.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/kmem.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <strings.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#include "ec.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecc_impl.h"
|
||||
|
||||
void SECITEM_FreeItem(SECItem *, PRBool);
|
||||
|
||||
SECItem *
|
||||
SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, unsigned int len,
|
||||
int kmflag)
|
||||
{
|
||||
SECItem *result = NULL;
|
||||
void *mark = NULL;
|
||||
|
||||
if (arena != NULL) {
|
||||
mark = PORT_ArenaMark(arena);
|
||||
}
|
||||
|
||||
if (item == NULL) {
|
||||
if (arena != NULL) {
|
||||
result = PORT_ArenaZAlloc(arena, sizeof(SECItem), kmflag);
|
||||
} else {
|
||||
result = PORT_ZAlloc(sizeof(SECItem), kmflag);
|
||||
}
|
||||
if (result == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
} else {
|
||||
PORT_Assert(item->data == NULL);
|
||||
result = item;
|
||||
}
|
||||
|
||||
result->len = len;
|
||||
if (len) {
|
||||
if (arena != NULL) {
|
||||
result->data = PORT_ArenaAlloc(arena, len, kmflag);
|
||||
} else {
|
||||
result->data = PORT_Alloc(len, kmflag);
|
||||
}
|
||||
if (result->data == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
} else {
|
||||
result->data = NULL;
|
||||
}
|
||||
|
||||
if (mark) {
|
||||
PORT_ArenaUnmark(arena, mark);
|
||||
}
|
||||
return(result);
|
||||
|
||||
loser:
|
||||
if ( arena != NULL ) {
|
||||
if (mark) {
|
||||
PORT_ArenaRelease(arena, mark);
|
||||
}
|
||||
if (item != NULL) {
|
||||
item->data = NULL;
|
||||
item->len = 0;
|
||||
}
|
||||
} else {
|
||||
if (result != NULL) {
|
||||
SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
|
||||
}
|
||||
/*
|
||||
* If item is not NULL, the above has set item->data and
|
||||
* item->len to 0.
|
||||
*/
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from,
|
||||
int kmflag)
|
||||
{
|
||||
to->type = from->type;
|
||||
if (from->data && from->len) {
|
||||
if ( arena ) {
|
||||
to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len,
|
||||
kmflag);
|
||||
} else {
|
||||
to->data = (unsigned char*) PORT_Alloc(from->len, kmflag);
|
||||
}
|
||||
|
||||
if (!to->data) {
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_Memcpy(to->data, from->data, from->len);
|
||||
to->len = from->len;
|
||||
} else {
|
||||
to->data = 0;
|
||||
to->len = 0;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
SECITEM_FreeItem(SECItem *zap, PRBool freeit)
|
||||
{
|
||||
if (zap) {
|
||||
#ifdef _KERNEL
|
||||
kmem_free(zap->data, zap->len);
|
||||
#else
|
||||
free(zap->data);
|
||||
#endif
|
||||
zap->data = 0;
|
||||
zap->len = 0;
|
||||
if (freeit) {
|
||||
#ifdef _KERNEL
|
||||
kmem_free(zap, sizeof (SECItem));
|
||||
#else
|
||||
free(zap);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
*********************************************************************** */
|
||||
|
||||
#ifndef _SECOIDT_H_
|
||||
#define _SECOIDT_H_
|
||||
|
||||
/*
|
||||
* secoidt.h - public data structures for ASN.1 OID functions
|
||||
*
|
||||
* $Id: secoidt.h,v 1.23 2007/05/05 22:45:16 nelson%bolyard.com Exp $
|
||||
*/
|
||||
|
||||
typedef struct SECOidDataStr SECOidData;
|
||||
typedef struct SECAlgorithmIDStr SECAlgorithmID;
|
||||
|
||||
/*
|
||||
** An X.500 algorithm identifier
|
||||
*/
|
||||
struct SECAlgorithmIDStr {
|
||||
SECItem algorithm;
|
||||
SECItem parameters;
|
||||
};
|
||||
|
||||
#define SEC_OID_SECG_EC_SECP192R1 SEC_OID_ANSIX962_EC_PRIME192V1
|
||||
#define SEC_OID_SECG_EC_SECP256R1 SEC_OID_ANSIX962_EC_PRIME256V1
|
||||
#define SEC_OID_PKCS12_KEY_USAGE SEC_OID_X509_KEY_USAGE
|
||||
|
||||
/* fake OID for DSS sign/verify */
|
||||
#define SEC_OID_SHA SEC_OID_MISS_DSS
|
||||
|
||||
typedef enum {
|
||||
INVALID_CERT_EXTENSION = 0,
|
||||
UNSUPPORTED_CERT_EXTENSION = 1,
|
||||
SUPPORTED_CERT_EXTENSION = 2
|
||||
} SECSupportExtenTag;
|
||||
|
||||
struct SECOidDataStr {
|
||||
SECItem oid;
|
||||
ECCurveName offset;
|
||||
const char * desc;
|
||||
unsigned long mechanism;
|
||||
SECSupportExtenTag supportedExtension;
|
||||
/* only used for x.509 v3 extensions, so
|
||||
that we can print the names of those
|
||||
extensions that we don't even support */
|
||||
};
|
||||
|
||||
#endif /* _SECOIDT_H_ */
|
@ -31,8 +31,6 @@
|
||||
* this test file was covered before with JDK-4936763.
|
||||
* @run main/othervm -Djdk.crypto.KeyAgreement.legacyKDF=true KeyAgreementTest
|
||||
* DiffieHellman DH SunJCE
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false KeyAgreementTest
|
||||
* ECDHNative EC SunEC
|
||||
* @run main KeyAgreementTest ECDH EC SunEC
|
||||
* @run main KeyAgreementTest XDH XDH SunEC
|
||||
*/
|
||||
@ -56,10 +54,6 @@ public class KeyAgreementTest {
|
||||
String provider = args[2];
|
||||
System.out.println("Testing " + kaAlgo);
|
||||
AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo);
|
||||
// Switch kaAlgo to ECDH as it is used for algorithm names
|
||||
if (kaAlgo.equals("ECDHNative")) {
|
||||
kaAlgo = "ECDH";
|
||||
}
|
||||
List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs();
|
||||
for (AlgorithmParameterSpec spec : specs) {
|
||||
testKeyAgreement(provider, kaAlgo, kpgAlgo, spec);
|
||||
@ -74,26 +68,7 @@ public class KeyAgreementTest {
|
||||
// EC curve supported for KeyGeneration can found between intersection
|
||||
// of curves define in
|
||||
// "java.base/share/classes/sun/security/util/CurveDB.java"
|
||||
// and
|
||||
// "jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c"
|
||||
ECDHNative(
|
||||
// SEC2 prime curves
|
||||
"secp112r1", "secp112r2", "secp128r1", "secp128r2", "secp160k1",
|
||||
"secp160r1", "secp192k1", "secp192r1", "secp224k1", "secp224r1",
|
||||
"secp256k1", "secp256r1", "secp384r1", "secp521r1", "SECP521R1",
|
||||
// ANSI X9.62 prime curves
|
||||
"X9.62 prime192v2", "X9.62 prime192v3", "X9.62 prime239v1",
|
||||
"X9.62 prime239v2", "X9.62 prime239v3",
|
||||
// SEC2 binary curves
|
||||
"sect113r1", "sect113r2", "sect131r1", "sect131r2", "sect163k1",
|
||||
"sect163r1", "sect163r2", "sect193r1", "sect193r2", "sect233k1",
|
||||
"sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1",
|
||||
"sect409r1", "sect571k1", "sect571r1",
|
||||
// ANSI X9.62 binary curves
|
||||
"X9.62 c2tnb191v1", "X9.62 c2tnb191v2", "X9.62 c2tnb191v3",
|
||||
"X9.62 c2tnb239v1", "X9.62 c2tnb239v2", "X9.62 c2tnb239v3",
|
||||
"X9.62 c2tnb359v1", "X9.62 c2tnb431r1"
|
||||
),
|
||||
|
||||
ECDH("secp256r1", "secp384r1", "secp521r1"),
|
||||
XDH("X25519", "X448", "x25519"),
|
||||
// There is no curve for DiffieHellman
|
||||
@ -105,7 +80,6 @@ public class KeyAgreementTest {
|
||||
// Generate AlgorithmParameterSpec for each KeyExchangeAlgorithm
|
||||
for (String crv : curves) {
|
||||
switch (this.name()) {
|
||||
case "ECDHNative":
|
||||
case "ECDH":
|
||||
specs.add(new ECGenParameterSpec(crv));
|
||||
break;
|
||||
@ -128,7 +102,7 @@ public class KeyAgreementTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform KeyAgreement operation using native as well as JCE provider.
|
||||
* Perform KeyAgreement operation
|
||||
*/
|
||||
private static void testKeyAgreement(String provider, String kaAlgo,
|
||||
String kpgAlgo, AlgorithmParameterSpec spec) throws Exception {
|
||||
|
@ -37,9 +37,9 @@
|
||||
* @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 4096
|
||||
* @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 6144
|
||||
* @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 8192
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false KeySizeTest ECDH SunEC EC 128
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false KeySizeTest ECDH SunEC EC 192
|
||||
* @run main/othervm KeySizeTest ECDH SunEC EC 256
|
||||
* @run main/othervm KeySizeTest ECDH SunEC EC 384
|
||||
* @run main/othervm KeySizeTest ECDH SunEC EC 521
|
||||
* @run main KeySizeTest XDH SunEC XDH 255
|
||||
* @run main KeySizeTest XDH SunEC XDH 448
|
||||
*/
|
||||
|
@ -372,14 +372,12 @@ public class SSLSocketTemplate {
|
||||
// Trusted certificates.
|
||||
protected final static Cert[] TRUSTED_CERTS = {
|
||||
Cert.CA_ECDSA_SECP256R1,
|
||||
Cert.CA_ECDSA_SECT283R1,
|
||||
Cert.CA_RSA_2048,
|
||||
Cert.CA_DSA_2048 };
|
||||
|
||||
// End entity certificate.
|
||||
protected final static Cert[] END_ENTITY_CERTS = {
|
||||
Cert.EE_ECDSA_SECP256R1,
|
||||
Cert.EE_ECDSA_SECT283R1,
|
||||
Cert.EE_RSA_2048,
|
||||
Cert.EE_EC_RSA_SECP256R1,
|
||||
Cert.EE_DSA_2048 };
|
||||
@ -705,32 +703,6 @@ public class SSLSocketTemplate {
|
||||
"p1YdWENftmDoNTJ3O6TNlXb90jKWgAirCXNBUompPtHKkO592eDyGcT1h8qjrKlm\n" +
|
||||
"Kw=="),
|
||||
|
||||
CA_ECDSA_SECT283R1(
|
||||
"EC",
|
||||
// SHA1withECDSA, curve sect283r1
|
||||
// Validity
|
||||
// Not Before: May 26 06:06:52 2020 GMT
|
||||
// Not After : May 21 06:06:52 2040 GMT
|
||||
// Subject Key Identifier:
|
||||
// CF:A3:99:ED:4C:6E:04:41:09:21:31:33:B6:80:D5:A7:BF:2B:98:04
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIB8TCCAY+gAwIBAgIJANQFsBngZ3iMMAsGByqGSM49BAEFADBdMQswCQYDVQQG\n" +
|
||||
"EwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNBMQ8wDQYDVQQKEwZPcmFjbGUx\n" +
|
||||
"DzANBgNVBAsTBkpQR1NRRTESMBAGA1UEAxMJc2VjdDI4M3IxMB4XDTIwMDUyNjE4\n" +
|
||||
"MDY1MloXDTQwMDUyMTE4MDY1MlowXTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB\n" +
|
||||
"MQswCQYDVQQHEwJTQTEPMA0GA1UEChMGT3JhY2xlMQ8wDQYDVQQLEwZKUEdTUUUx\n" +
|
||||
"EjAQBgNVBAMTCXNlY3QyODNyMTBeMBAGByqGSM49AgEGBSuBBAARA0oABALatmDt\n" +
|
||||
"QIhjpK4vJjv4GgC8CUH/VAWLUSQRU7yGGQ3NF8rVBARv0aehiII0nzjDVX5KrP/A\n" +
|
||||
"w/DmW7q8PfEAIktuaA/tcKv/OKMyMDAwHQYDVR0OBBYEFM+jme1MbgRBCSExM7aA\n" +
|
||||
"1ae/K5gEMA8GA1UdEwEB/wQFMAMBAf8wCwYHKoZIzj0EAQUAA08AMEwCJAGHsAP8\n" +
|
||||
"HlcVqszra+fxq35juTxHJIfxTKIr7f54Ywtz7AJowgIkAxydv8g+dkuniOUAj0Xt\n" +
|
||||
"FnGVp6HzKX5KM1zLpfqmix8ZPP/A\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"MIGQAgEAMBAGByqGSM49AgEGBSuBBAARBHkwdwIBAQQkAdcyn/FxiNvuTsSgDehq\n" +
|
||||
"SGFiTxAKNMMJfmsO6GHekzszFqjPoUwDSgAEAtq2YO1AiGOkri8mO/gaALwJQf9U\n" +
|
||||
"BYtRJBFTvIYZDc0XytUEBG/Rp6GIgjSfOMNVfkqs/8DD8OZburw98QAiS25oD+1w\n" +
|
||||
"q/84"),
|
||||
|
||||
CA_RSA_2048(
|
||||
"RSA",
|
||||
// SHA256withRSA, 2048 bits
|
||||
@ -917,33 +889,6 @@ public class SSLSocketTemplate {
|
||||
"MEcCAQAwBQYDK2VxBDsEOd6/hRZqkUyTlJSwdN5gO/HnoWYda1fD83YUm5j6m2Bg\n" +
|
||||
"hAQi+QadFsQLD7R6PI/4Q0twXqlKnxU5Ug=="),
|
||||
|
||||
EE_ECDSA_SECT283R1(
|
||||
"EC",
|
||||
// SHA1withECDSA, curve sect283r1
|
||||
// Validity
|
||||
// Not Before: May 26 06:08:15 2020 GMT
|
||||
// Not After : May 21 06:08:15 2040 GMT
|
||||
// Authority Key Identifier:
|
||||
// CF:A3:99:ED:4C:6E:04:41:09:21:31:33:B6:80:D5:A7:BF:2B:98:04
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICFTCCAbOgAwIBAgIJAM0Dd9zxR9CeMAsGByqGSM49BAEFADBdMQswCQYDVQQG\n" +
|
||||
"EwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNBMQ8wDQYDVQQKEwZPcmFjbGUx\n" +
|
||||
"DzANBgNVBAsTBkpQR1NRRTESMBAGA1UEAxMJc2VjdDI4M3IxMB4XDTIwMDUyNjE4\n" +
|
||||
"MDgxNVoXDTQwMDUyMTE4MDgxNVowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB\n" +
|
||||
"MQswCQYDVQQHEwJTQTEPMA0GA1UEChMGT3JhY2xlMQ8wDQYDVQQLEwZKUEdTUUUx\n" +
|
||||
"FTATBgNVBAMMDHNlY3QyODNyMV9lZTBeMBAGByqGSM49AgEGBSuBBAARA0oABAMP\n" +
|
||||
"oaMP2lIiCrNaFSePtZA8nBnqJXSGCz8kosKeYTqz/SPE1AN6BvM4xl0kPQZvJWMz\n" +
|
||||
"fyTcm2Ar0PdbIh8f22vJfO+0JpfhnqNTMFEwHQYDVR0OBBYEFOzDGNWQhslU5ei4\n" +
|
||||
"SYda/ro9DickMA8GA1UdEwQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUz6OZ7UxuBEEJ\n" +
|
||||
"ITEztoDVp78rmAQwCwYHKoZIzj0EAQUAA08AMEwCJALYBWSYdbhRiW4mNulQh6/v\n" +
|
||||
"dfHG3y/oMjzJEmT/A0WYl96ohgIkAbDC0Ke632RXtCZ4xa2FrmzP41Vb80mSH1iY\n" +
|
||||
"FCJ3LVoTEUgN\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"MIGQAgEAMBAGByqGSM49AgEGBSuBBAARBHkwdwIBAQQkAXq9LPYU+XSrImPzgO1e\n" +
|
||||
"hsgjfTBXlWGveFUtn0OHPtbp7hzpoUwDSgAEAw+how/aUiIKs1oVJ4+1kDycGeol\n" +
|
||||
"dIYLPySiwp5hOrP9I8TUA3oG8zjGXSQ9Bm8lYzN/JNybYCvQ91siHx/ba8l877Qm\n" +
|
||||
"l+Ge"),
|
||||
|
||||
EE_ECDSA_SECP256R1(
|
||||
"EC",
|
||||
// SHA256withECDSA, curve secp256r1
|
||||
|
@ -31,7 +31,7 @@
|
||||
* jdk.jartool
|
||||
* jdk.crypto.ec
|
||||
* @build jdk.test.lib.util.JarUtils
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false Spec
|
||||
* @run main/othervm Spec
|
||||
*/
|
||||
|
||||
import com.sun.jarsigner.ContentSigner;
|
||||
@ -190,7 +190,7 @@ public class Spec {
|
||||
.equals("SHA256withDSA"));
|
||||
|
||||
kpg = KeyPairGenerator.getInstance("EC");
|
||||
kpg.initialize(192);
|
||||
kpg.initialize(256);
|
||||
assertTrue(JarSigner.Builder
|
||||
.getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
|
||||
.equals("SHA256withECDSA"));
|
||||
@ -198,7 +198,7 @@ public class Spec {
|
||||
assertTrue(JarSigner.Builder
|
||||
.getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
|
||||
.equals("SHA384withECDSA"));
|
||||
kpg.initialize(571);
|
||||
kpg.initialize(521);
|
||||
assertTrue(JarSigner.Builder
|
||||
.getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
|
||||
.equals("SHA512withECDSA"));
|
||||
|
@ -66,10 +66,7 @@ public class ECDSAJavaVerify {
|
||||
"SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", "SHA512withECDSA"};
|
||||
|
||||
static final String[] ALL_CURVES = new String[] {
|
||||
"secp128r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1"};
|
||||
|
||||
static final List<String> ALL_JAVA_CURVES
|
||||
= List.of("secp256r1", "secp384r1", "secp521r1");
|
||||
"secp256r1", "secp384r1", "secp521r1"};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 1) {
|
||||
@ -100,8 +97,7 @@ public class ECDSAJavaVerify {
|
||||
= launchingConnector.defaultArguments();
|
||||
arguments.get("main").setValue(ECDSAJavaVerify.class.getName());
|
||||
arguments.get("options").setValue(
|
||||
"-cp " + System.getProperty("test.classes") +
|
||||
" -Djdk.sunec.disableNative=false");
|
||||
"-cp " + System.getProperty("test.classes"));
|
||||
VirtualMachine vm = launchingConnector.launch(arguments);
|
||||
|
||||
MethodEntryRequest req = vm.eventRequestManager()
|
||||
@ -117,7 +113,7 @@ public class ECDSAJavaVerify {
|
||||
int pos = 0;
|
||||
for (String dummy : ALL_ALGS) {
|
||||
for (String curve : ALL_CURVES) {
|
||||
char caller = ALL_JAVA_CURVES.contains(curve) ? 'J' : 'N';
|
||||
char caller = 'J';
|
||||
// For each case, Signature::verify is called twice
|
||||
expected[pos++] = caller;
|
||||
expected[pos++] = caller;
|
||||
@ -150,9 +146,6 @@ public class ECDSAJavaVerify {
|
||||
case "verifySignedDigestImpl": // the java impl
|
||||
result[pos] = expected[pos] != 'J' ? 'x' : 'v';
|
||||
break;
|
||||
case "verifySignedDigest": // the native impl
|
||||
result[pos] = expected[pos] != 'N' ? 'x' : 'v';
|
||||
break;
|
||||
}
|
||||
}
|
||||
vm.resume();
|
||||
|
@ -36,7 +36,7 @@ import java.util.*;
|
||||
* group order.
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Convert
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false SignatureDigestTruncate
|
||||
* @run main/othervm SignatureDigestTruncate
|
||||
*/
|
||||
public class SignatureDigestTruncate {
|
||||
|
||||
@ -117,12 +117,12 @@ public class SignatureDigestTruncate {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
runTest("SHA384withECDSAinP1363Format", "sect283r1",
|
||||
runTest("SHA384withECDSAinP1363Format", "secp256r1",
|
||||
"abcdef10234567", "010203040506070809",
|
||||
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d" +
|
||||
"1e1f20212223",
|
||||
"01d7544b5d3935216bd45e2f8042537e1e0296a11e0eb96666199281b409" +
|
||||
"42abccd5358a035de8a314d3e6c2a97614daebf5fb1313540eec3f9a3272" +
|
||||
"068aa10922ccae87d255c84c");
|
||||
"1e1f20212223",
|
||||
"d83534beccde787f9a4c6b0408337d9b9ca2e0a0259228526c15cc17a1d6" +
|
||||
"4da6b34bf21b3bc4488c591d8ac9c33d93c7c6137e2ab4c503a42da7" +
|
||||
"2fe0b6dda4c4");
|
||||
}
|
||||
}
|
||||
|
@ -48,13 +48,12 @@ import java.security.Security;
|
||||
/*
|
||||
* Leverage the collection of EC tests used by PKCS11
|
||||
*
|
||||
* NOTE: the following 6 files were copied here from the PKCS11 EC Test area
|
||||
* NOTE: the following 5 files were copied here from the PKCS11 EC Test area
|
||||
* and must be kept in sync with the originals:
|
||||
*
|
||||
* ../pkcs11/ec/p12passwords.txt
|
||||
* ../pkcs11/ec/certs/sunlabscerts.pem
|
||||
* ../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12
|
||||
* ../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12
|
||||
* ../pkcs11/sslecc/keystore
|
||||
* ../pkcs11/sslecc/truststore
|
||||
*/
|
||||
@ -99,14 +98,21 @@ public class TestEC {
|
||||
* The entry point used for each test is its instance method
|
||||
* called main (not its static method called main).
|
||||
*/
|
||||
System.out.println("TestECDH");
|
||||
new TestECDH().main(p);
|
||||
System.out.println("TestECDSA");
|
||||
new TestECDSA().main(p);
|
||||
System.out.println("TestCurves");
|
||||
new TestCurves().main(p);
|
||||
System.out.println("TestKeyFactory");
|
||||
new TestKeyFactory().main(p);
|
||||
System.out.println("TestECGenSpec");
|
||||
new TestECGenSpec().main(p);
|
||||
System.out.println("ReadPKCS12");
|
||||
new ReadPKCS12().main(p);
|
||||
System.out.println("ReadCertificate");
|
||||
new ReadCertificates().main(p);
|
||||
|
||||
System.out.println("ClientJSSEServerJSSE");
|
||||
new ClientJSSEServerJSSE().main(p);
|
||||
|
||||
long stop = System.currentTimeMillis();
|
||||
|
Binary file not shown.
Binary file not shown.
@ -29,9 +29,9 @@
|
||||
* @library /test/lib ..
|
||||
* @library ../../../../java/security/testlibrary
|
||||
* @key randomness
|
||||
* @modules jdk.crypto.cryptoki
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false ReadPKCS12
|
||||
* @run main/othervm -Djdk.sunec.disableNative=false ReadPKCS12 sm policy
|
||||
* @modules jdk.crypto.cryptoki jdk.crypto.ec/sun.security.ec
|
||||
* @run main/othervm ReadPKCS12
|
||||
* @run main/othervm ReadPKCS12 sm policy
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -124,9 +124,12 @@ public class TestECDH extends PKCS11Test {
|
||||
return;
|
||||
}
|
||||
|
||||
test(p, pub192a, priv192a, pub192b, priv192b, secret192);
|
||||
test(p, pub163a, priv163a, pub163b, priv163b, secret163);
|
||||
|
||||
if (getSupportedECParameterSpec("secp192r1", p).isPresent()) {
|
||||
test(p, pub192a, priv192a, pub192b, priv192b, secret192);
|
||||
}
|
||||
if (getSupportedECParameterSpec("sect163r1", p).isPresent()) {
|
||||
test(p, pub163a, priv163a, pub163b, priv163b, secret163);
|
||||
}
|
||||
if (getSupportedECParameterSpec("brainpoolP256r1", p).isPresent()) {
|
||||
test(p, pubBrainpoolP256r1a, privBrainpoolP256r1a, pubBrainpoolP256r1b, privBrainpoolP256r1b, secretBrainpoolP256r1);
|
||||
}
|
||||
|
@ -156,12 +156,14 @@ public class TestECDSA extends PKCS11Test {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getNSSECC() != ECCState.Basic) {
|
||||
if (getSupportedECParameterSpec("secp192r1", provider).isPresent()) {
|
||||
test(provider, pub192, priv192, sig192);
|
||||
}
|
||||
if (getSupportedECParameterSpec("sect163r1", provider).isPresent()) {
|
||||
test(provider, pub163, priv163, sig163);
|
||||
}
|
||||
if (getSupportedECParameterSpec("sect571r1", provider).isPresent()) {
|
||||
test(provider, pub571, priv571, sig571);
|
||||
} else {
|
||||
System.out.println("ECC Basic only, skipping 192, 163 and 571.");
|
||||
}
|
||||
test(provider, pub521, priv521, sig521);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -130,17 +130,12 @@ public class TestKeyFactory extends PKCS11Test {
|
||||
System.out.println("Provider does not support EC, skipping");
|
||||
return;
|
||||
}
|
||||
int[] keyLengths = {192, 163, 409, 521};
|
||||
int len = 0;
|
||||
if (getNSSECC() == ECCState.Basic) {
|
||||
System.out.println("NSS Basic ECC only. Skipping 192, 163, & 409");
|
||||
len = 3;
|
||||
}
|
||||
int[] keyLengths = {256, 521};
|
||||
KeyFactory kf = KeyFactory.getInstance("EC", p);
|
||||
for (; keyLengths.length > len ; len++) {
|
||||
System.out.println("Length "+keyLengths[len]);
|
||||
for (int len : keyLengths) {
|
||||
System.out.println("Length " + len);
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
|
||||
kpg.initialize(keyLengths[len]);
|
||||
kpg.initialize(len);
|
||||
KeyPair kp = kpg.generateKeyPair();
|
||||
test(kf, kp.getPrivate());
|
||||
test(kf, kp.getPublic());
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -52,8 +52,6 @@ public class DKSTest {
|
||||
new KeyStore.PasswordProtection("test12".toCharArray()));
|
||||
put("eckeystore1",
|
||||
new KeyStore.PasswordProtection("password".toCharArray()));
|
||||
put("eckeystore2",
|
||||
new KeyStore.PasswordProtection("password".toCharArray()));
|
||||
put("truststore",
|
||||
new KeyStore.PasswordProtection("changeit".toCharArray()));
|
||||
put("empty",
|
||||
@ -69,8 +67,6 @@ public class DKSTest {
|
||||
new KeyStore.PasswordProtection("wrong".toCharArray()));
|
||||
put("eckeystore1",
|
||||
new KeyStore.PasswordProtection("wrong".toCharArray()));
|
||||
put("eckeystore2",
|
||||
new KeyStore.PasswordProtection("wrong".toCharArray()));
|
||||
}};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@ -154,7 +150,7 @@ public class DKSTest {
|
||||
* domain keystore: keystores
|
||||
*/
|
||||
config = new URI(CONFIG + "#keystores");
|
||||
expected = 2 + 1 + 1 + 1;
|
||||
expected = 2 + 1 + 1;
|
||||
keystore = KeyStore.getInstance("DKS");
|
||||
// load entries
|
||||
keystore.load(new DomainLoadStoreParameter(config, PASSWORDS));
|
||||
|
@ -25,8 +25,6 @@ domain keystores
|
||||
keystoreType="CaseExactJKS"
|
||||
keystoreURI="${test.src}/pw.jks";
|
||||
keystore eckeystore1
|
||||
keystoreURI="${test.src}/../../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12";
|
||||
keystore eckeystore2
|
||||
keystoreURI="${test.src}/../../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12";
|
||||
};
|
||||
|
||||
@ -40,8 +38,6 @@ domain keystores_tmp
|
||||
keystoreType="CaseExactJKS"
|
||||
keystoreURI="${user.dir}/pw.jks_tmp";
|
||||
keystore eckeystore1
|
||||
keystoreURI="${user.dir}/sect193r1server-rsa1024ca.p12_tmp";
|
||||
keystore eckeystore2
|
||||
keystoreURI="${user.dir}/secp256r1server-secp384r1ca.p12_tmp";
|
||||
};
|
||||
|
||||
|
@ -25,10 +25,10 @@
|
||||
* @test
|
||||
* @bug 8246330
|
||||
* @library /javax/net/ssl/templates
|
||||
* @run main/othervm -Djdk.tls.namedGroups="sect283r1"
|
||||
* @run main/othervm -Djdk.tls.namedGroups="secp384r1"
|
||||
DisabledCurve DISABLE_NONE PASS
|
||||
* @run main/othervm -Djdk.tls.namedGroups="sect283r1"
|
||||
DisabledCurve sect283r1 FAIL
|
||||
* @run main/othervm -Djdk.tls.namedGroups="secp384r1"
|
||||
DisabledCurve secp384r1 FAIL
|
||||
*/
|
||||
import java.security.Security;
|
||||
import java.util.Arrays;
|
||||
@ -49,18 +49,18 @@ public class DisabledCurve extends SSLSocketTemplate {
|
||||
protected SSLContext createClientSSLContext() throws Exception {
|
||||
return createSSLContext(
|
||||
new SSLSocketTemplate.Cert[] {
|
||||
SSLSocketTemplate.Cert.CA_ECDSA_SECT283R1 },
|
||||
SSLSocketTemplate.Cert.CA_ECDSA_SECP384R1 },
|
||||
new SSLSocketTemplate.Cert[] {
|
||||
SSLSocketTemplate.Cert.EE_ECDSA_SECT283R1 },
|
||||
SSLSocketTemplate.Cert.EE_ECDSA_SECP384R1 },
|
||||
getClientContextParameters());
|
||||
}
|
||||
|
||||
protected SSLContext createServerSSLContext() throws Exception {
|
||||
return createSSLContext(
|
||||
new SSLSocketTemplate.Cert[] {
|
||||
SSLSocketTemplate.Cert.CA_ECDSA_SECT283R1 },
|
||||
SSLSocketTemplate.Cert.CA_ECDSA_SECP384R1 },
|
||||
new SSLSocketTemplate.Cert[] {
|
||||
SSLSocketTemplate.Cert.EE_ECDSA_SECT283R1 },
|
||||
SSLSocketTemplate.Cert.EE_ECDSA_SECP384R1 },
|
||||
getServerContextParameters());
|
||||
}
|
||||
|
||||
@ -89,22 +89,23 @@ public class DisabledCurve extends SSLSocketTemplate {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String expected = args[1];
|
||||
String disabledName = ("DISABLE_NONE".equals(args[0]) ? "" : args[0]);
|
||||
boolean disabled = false;
|
||||
if (disabledName.equals("")) {
|
||||
Security.setProperty("jdk.disabled.namedCurves", "");
|
||||
} else {
|
||||
disabled = true;
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms", "secp384r1");
|
||||
}
|
||||
System.setProperty("jdk.sunec.disableNative", "false");
|
||||
|
||||
for (index = 0; index < protocols.length; index++) {
|
||||
try {
|
||||
(new DisabledCurve()).run();
|
||||
if (expected.equals("FAIL")) {
|
||||
throw new RuntimeException(
|
||||
"The test case should not reach here");
|
||||
"Expected test to fail, but it passed");
|
||||
}
|
||||
} catch (SSLException | IllegalStateException ssle) {
|
||||
if ((expected.equals("FAIL"))
|
||||
&& Security.getProperty("jdk.disabled.namedCurves")
|
||||
.contains(disabledName)) {
|
||||
if (expected.equals("FAIL") && disabled) {
|
||||
System.out.println(
|
||||
"Expected exception was thrown: TEST PASSED");
|
||||
} else {
|
||||
|
@ -93,11 +93,6 @@ public class RestrictedAlgo {
|
||||
System.out.println("\nTesting DSA Keysize: DSA keySize < 1024\n");
|
||||
test("DSA", "SHA256withDSA", "KeySizeDSA", "SHA256", true,
|
||||
"-keysize", "512");
|
||||
|
||||
System.out.println("\nTesting Native Curve:"
|
||||
+ " include jdk.disabled.namedCurves\n");
|
||||
test("EC", "SHA256withECDSA", "curve", "SHA256", true,
|
||||
"-groupname", "secp112r1");
|
||||
}
|
||||
|
||||
private static void test(String keyAlg, String sigAlg, String aliasPrefix,
|
||||
@ -123,8 +118,7 @@ public class RestrictedAlgo {
|
||||
"-ext", "bc:c",
|
||||
"-keyalg", keyAlg,
|
||||
"-sigalg", sigAlg,
|
||||
"-alias", alias,
|
||||
"-J-Djdk.sunec.disableNative=false");
|
||||
"-alias", alias);
|
||||
for (String additionalCMDArg : additionalCmdArgs) {
|
||||
cmd.add(additionalCMDArg);
|
||||
}
|
||||
@ -147,8 +141,7 @@ public class RestrictedAlgo {
|
||||
"-digestalg", digestAlg,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
alias,
|
||||
"-J-Djdk.sunec.disableNative=false");
|
||||
alias);
|
||||
|
||||
OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd)
|
||||
.shouldHaveExitValue(0);
|
||||
@ -162,8 +155,7 @@ public class RestrictedAlgo {
|
||||
System.out.println("\nTesting JarSigner Verification\n");
|
||||
List<String> cmd = prepareCommand(
|
||||
"-verify",
|
||||
SIGNED_JARFILE,
|
||||
"-J-Djdk.sunec.disableNative=false");
|
||||
SIGNED_JARFILE);
|
||||
|
||||
OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd)
|
||||
.shouldHaveExitValue(0);
|
||||
|
@ -65,11 +65,6 @@ public class GroupName {
|
||||
.shouldNotContain("Specifying -keysize for generating EC keys is deprecated");
|
||||
checkCurveName("e", "secp256r1");
|
||||
|
||||
gen("f", "-J-Djdk.sunec.disableNative=false -keyalg EC -groupname brainpoolP256r1")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldNotContain("Specifying -keysize for generating EC keys is deprecated");
|
||||
checkCurveName("f", "brainpoolP256r1");
|
||||
|
||||
kt("-list -v")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("Subject Public Key Algorithm: 256-bit EC (secp256r1) key");
|
||||
|
@ -41,10 +41,6 @@ public class KeyAlg {
|
||||
keytool("-printcert -file user.crt")
|
||||
.shouldMatch("Signature algorithm name:.*SHA1withECDSA")
|
||||
.shouldMatch("Subject Public Key Algorithm:.*1024.*RSA");
|
||||
keytool("-genkeypair -alias e -dname CN=e " +
|
||||
"-J-Djdk.sunec.disableNative=false -keyalg EC " +
|
||||
"-groupname brainpoolP256r1")
|
||||
.shouldContain("Generating 256 bit EC (brainpoolP256r1) key pair");
|
||||
keytool("-genkeypair -alias f -dname CN=f -keyalg EC")
|
||||
.shouldContain("Generating 256 bit EC (secp256r1) key pair");
|
||||
keytool("-genkeypair -alias g -dname CN=g -keyalg EC -keysize 384")
|
||||
|
@ -55,11 +55,9 @@ public class DefaultSignatureAlgorithm {
|
||||
check("DSA", 1024, null, "SHA256withDSA");
|
||||
check("DSA", 3072, null, "SHA256withDSA");
|
||||
|
||||
check("EC", 192, null, "SHA256withECDSA");
|
||||
check("EC", 384, null, "SHA384withECDSA");
|
||||
check("EC", 571, null, "SHA512withECDSA");
|
||||
|
||||
check("EC", 571, "SHA256withECDSA", "SHA256withECDSA");
|
||||
check("EC", 384, "SHA256withECDSA", "SHA256withECDSA");
|
||||
}
|
||||
|
||||
private static void check(String keyAlg, int keySize,
|
||||
@ -82,8 +80,7 @@ public class DefaultSignatureAlgorithm {
|
||||
|
||||
static OutputAnalyzer genkeypair(String alias, String options)
|
||||
throws Exception {
|
||||
String patchArg = "-J-Djdk.sunec.disableNative=false " +
|
||||
"-J--patch-module=java.base="
|
||||
String patchArg = "-J--patch-module=java.base="
|
||||
+ System.getProperty("test.classes")
|
||||
+ File.separator + "patches" + File.separator + "java.base"
|
||||
+ " -J--patch-module=jdk.crypto.ec="
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -58,14 +58,6 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
public KeyPair generateKeyPair() {
|
||||
BigInteger s, x, y;
|
||||
switch (keySize) {
|
||||
case 192:
|
||||
s = new BigInteger("144089953963995451666433763881605261867377"
|
||||
+ "0287449914970417");
|
||||
x = new BigInteger("527580219290493448707803038403444129676461"
|
||||
+ "560927008883862");
|
||||
y = new BigInteger("171489247081620145247240656640887886126295"
|
||||
+ "376102134763235");
|
||||
break;
|
||||
case 384:
|
||||
s = new BigInteger("230878276322370828604837367594276033697165"
|
||||
+ "328633328282930557390817326627704675451851870430805"
|
||||
@ -77,22 +69,10 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
+ "792287657810480793861620950159864617021540168828129"
|
||||
+ "97920015041145259782242");
|
||||
break;
|
||||
case 571:
|
||||
s = new BigInteger("102950007413729156017516513076331886543538"
|
||||
+ "947044937190140406420556321983301533699021909556189"
|
||||
+ "150601557539520495361099574425100081169640300555562"
|
||||
+ "4280643194744140660275077121");
|
||||
x = new BigInteger("640598847385582251482893323029655037929442"
|
||||
+ "593800810090252942944624854811134311418807076811195"
|
||||
+ "132373308708007447666896675761104237802118413642543"
|
||||
+ "8277858107132017492037336593");
|
||||
y = new BigInteger("254271270803422773271985083014247202480077"
|
||||
+ "131823713050110789460550383275777195766342550786766"
|
||||
+ "080401402424961690914429074822281551140068729472439"
|
||||
+ "477216613432839953714415981");
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unsupported keysize " + keySize);
|
||||
throw new AssertionError("SunEC ECKeyPairGenerator" +
|
||||
"has been patched. Key size " + keySize +
|
||||
" is not supported");
|
||||
}
|
||||
ECParameterSpec ecParams = ECUtil.getECParameterSpec(null, keySize);
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user