Bug 1894459 - land NSS a4c9d2760c66 UPGRADE_NSS_RELEASE, r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D212150
This commit is contained in:
John Schanck 2024-05-30 22:55:59 +00:00
parent dc8279def2
commit 4d4015d3c2
157 changed files with 9066 additions and 41195 deletions

View File

@ -13,7 +13,7 @@ system_lib_option(
imply_option("--with-system-nspr", True, when="--with-system-nss")
nss_pkg = pkg_check_modules(
"NSS", "nss >= 3.100", when="--with-system-nss", config=False
"NSS", "nss >= 3.101", when="--with-system-nss", config=False
)
set_config("MOZ_SYSTEM_NSS", True, when="--with-system-nss")

View File

@ -178,8 +178,11 @@ HASH_Create
HASH_Destroy
HASH_End
HASH_GetHashObject
HASH_GetHashOidTagByHMACOidTag
HASH_GetHashOidTagByHMACOidTag_Util
HASH_GetHashOidTagByHashType
HASH_GetHashTypeByOidTag
HASH_GetHashTypeByOidTag_Util
HASH_GetType
HASH_HashBuf
HASH_ResultLenByOidTag

View File

@ -76,6 +76,16 @@ tasks:
features:
taskclusterProxy: true
artifacts:
'public/docker-contexts':
type: 'directory'
path: '/home/worker/docker-contexts'
# This needs to be at least the deadline of the
# decision task + the docker-image task deadlines.
# It is set to a week to allow for some time for
# debugging, but they are not useful long-term.
expires: {$fromNow: '7 day'}
extra:
treeherder:
symbol: D

View File

@ -1 +1 @@
NSS_3_100_RTM
a4c9d2760c66

View File

@ -1,24 +1,28 @@
9 Added functions:
'function SECOidTag HASH_GetHashOidTagByHMACOidTag(SECOidTag)' {HASH_GetHashOidTagByHMACOidTag@@NSS_3.101}
'function int PK11_GetMaxKeyLength(CK_MECHANISM_TYPE)' {PK11_GetMaxKeyLength@@NSS_3.101}
'function SECStatus PK11_ReadDistrustAfterAttribute(PK11SlotInfo*, CK_OBJECT_HANDLE, CK_ATTRIBUTE_TYPE, PRBool*, PRTime*)' {PK11_ReadDistrustAfterAttribute@@NSS_3.101}
'function SECStatus SECKEY_EnforceKeySize(KeyType, unsigned int, SECErrorCodes)' {SECKEY_EnforceKeySize@@NSS_3.101}
'function unsigned int SECKEY_PrivateKeyStrengthInBits(const SECKEYPrivateKey*)' {SECKEY_PrivateKeyStrengthInBits@@NSS_3.101}
'function CK_RSA_PKCS_MGF_TYPE SEC_GetMgfTypeByOidTag(SECOidTag)' {SEC_GetMgfTypeByOidTag@@NSS_3.101}
'function SECOidTag SEC_PKCS5GetCryptoFromAlgTag(SECOidTag)' {SEC_PKCS5GetCryptoFromAlgTag@@NSS_3.101}
'function SECOidTag SEC_PKCS5GetHashAlgorithm(SECAlgorithmID*)' {SEC_PKCS5GetHashAlgorithm@@NSS_3.101}
'function SECOidTag SEC_PKCS5GetHashFromAlgTag(SECOidTag)' {SEC_PKCS5GetHashFromAlgTag@@NSS_3.101}
1 function with some indirect sub-type change:
[C]'function SECStatus CERT_AddOCSPAcceptableResponses(CERTOCSPRequest*, SECOidTag, ...)' at ocsp.c:2202:1 has some indirect sub-type changes:
parameter 2 of type 'typedef SECOidTag' has sub-type changes:
underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed:
type size hasn't changed
10 enumerator insertions:
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA1KDF_SCHEME' value '375'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA224KDF_SCHEME' value '376'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA256KDF_SCHEME' value '377'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA384KDF_SCHEME' value '378'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA512KDF_SCHEME' value '379'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA1KDF_SCHEME' value '380'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA224KDF_SCHEME' value '381'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA256KDF_SCHEME' value '382'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA384KDF_SCHEME' value '383'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA512KDF_SCHEME' value '384'
3 enumerator insertions:
'__anonymous_enum__::SEC_OID_RC2_64_CBC' value '385'
'__anonymous_enum__::SEC_OID_RC2_128_CBC' value '386'
'__anonymous_enum__::SEC_OID_ECDH_KEA' value '387'
1 enumerator change:
'__anonymous_enum__::SEC_OID_TOTAL' from value '375' to '385' at secoidt.h:34:1
'__anonymous_enum__::SEC_OID_TOTAL' from value '385' to '388' at secoidt.h:34:1

View File

@ -1,24 +1,27 @@
7 Added functions:
'function SECOidTag HASH_GetHMACOidTagByHashOidTag_Util(SECOidTag)' {HASH_GetHMACOidTagByHashOidTag_Util@@NSSUTIL_3.101}
'function SECOidTag HASH_GetHashOidTagByHMACOidTag_Util(SECOidTag)' {HASH_GetHashOidTagByHMACOidTag_Util@@NSSUTIL_3.101}
'function SECOidTag HASH_GetHashOidTagByHashType_Util(HASH_HashType)' {HASH_GetHashOidTagByHashType_Util@@NSSUTIL_3.101}
'function HASH_HashType HASH_GetHashTypeByOidTag_Util(SECOidTag)' {HASH_GetHashTypeByOidTag_Util@@NSSUTIL_3.101}
'function SECStatus NSS_GetAlgorithmPolicyAll(PRUint32, PRUint32, SECOidTag**, int*)' {NSS_GetAlgorithmPolicyAll@@NSSUTIL_3.101}
'function SECStatus NSS_SetAlgorithmPolicyAll(PRUint32, PRUint32)' {NSS_SetAlgorithmPolicyAll@@NSSUTIL_3.101}
'function SECOidTag SECOID_GetTotalTags()' {SECOID_GetTotalTags@@NSSUTIL_3.101}
1 function with some indirect sub-type change:
[C]'function SECStatus NSS_GetAlgorithmPolicy(SECOidTag, PRUint32*)' at secoid.c:2336:1 has some indirect sub-type changes:
[C]'function SECStatus NSS_GetAlgorithmPolicy(SECOidTag, PRUint32*)' at secoid.c:2366:1 has some indirect sub-type changes:
parameter 1 of type 'typedef SECOidTag' has sub-type changes:
underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed:
type size hasn't changed
10 enumerator insertions:
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA1KDF_SCHEME' value '375'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA224KDF_SCHEME' value '376'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA256KDF_SCHEME' value '377'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA384KDF_SCHEME' value '378'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA512KDF_SCHEME' value '379'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA1KDF_SCHEME' value '380'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA224KDF_SCHEME' value '381'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA256KDF_SCHEME' value '382'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA384KDF_SCHEME' value '383'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA512KDF_SCHEME' value '384'
3 enumerator insertions:
'__anonymous_enum__::SEC_OID_RC2_64_CBC' value '385'
'__anonymous_enum__::SEC_OID_RC2_128_CBC' value '386'
'__anonymous_enum__::SEC_OID_ECDH_KEA' value '387'
1 enumerator change:
'__anonymous_enum__::SEC_OID_TOTAL' from value '375' to '385' at secoidt.h:34:1
'__anonymous_enum__::SEC_OID_TOTAL' from value '385' to '388' at secoidt.h:34:1

View File

@ -1,4 +1,9 @@
2 Added functions:
'function PRBool SEC_PKCS12CipherAllowed(SECOidTag, SECOidTag)' {SEC_PKCS12CipherAllowed@@NSS_3.101}
'function PRBool SEC_PKCS12IntegrityHashAllowed(SECOidTag, PRBool)' {SEC_PKCS12IntegrityHashAllowed@@NSS_3.101}
1 function with some indirect sub-type change:
[C]'function PK11SymKey* NSS_CMSContentInfo_GetBulkKey(NSSCMSContentInfo*)' at cmscinfo.c:426:1 has some indirect sub-type changes:
@ -10,7 +15,7 @@
type of 'NSSCMSContent NSSCMSContentInfoStr::content' changed:
underlying type 'union NSSCMSContentUnion' at cmst.h:113:1 changed:
type size hasn't changed
2 data member changes (2 filtered):
1 data member changes (3 filtered):
type of 'NSSCMSEncryptedData* NSSCMSContentUnion::encryptedData' changed:
in pointed to type 'typedef NSSCMSEncryptedData' at cmst.h:65:1:
underlying type 'struct NSSCMSEncryptedDataStr' at cmst.h:470:1 changed:
@ -24,91 +29,24 @@
1 data member change:
type of 'SECOidData* NSSCMSAttributeStr::typeTag' changed:
in pointed to type 'typedef SECOidData' at secoidt.h:16:1:
underlying type 'struct SECOidDataStr' at secoidt.h:547:1 changed:
underlying type 'struct SECOidDataStr' at secoidt.h:550:1 changed:
type size hasn't changed
1 data member change:
type of 'SECOidTag SECOidDataStr::offset' changed:
underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed:
type size hasn't changed
10 enumerator insertions:
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA1KDF_SCHEME' value '375'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA224KDF_SCHEME' value '376'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA256KDF_SCHEME' value '377'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA384KDF_SCHEME' value '378'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_STDDH_SHA512KDF_SCHEME' value '379'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA1KDF_SCHEME' value '380'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA224KDF_SCHEME' value '381'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA256KDF_SCHEME' value '382'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA384KDF_SCHEME' value '383'
'__anonymous_enum__::SEC_OID_DHSINGLEPASS_COFACTORDH_SHA512KDF_SCHEME' value '384'
3 enumerator insertions:
'__anonymous_enum__::SEC_OID_RC2_64_CBC' value '385'
'__anonymous_enum__::SEC_OID_RC2_128_CBC' value '386'
'__anonymous_enum__::SEC_OID_ECDH_KEA' value '387'
1 enumerator change:
'__anonymous_enum__::SEC_OID_TOTAL' from value '375' to '385' at secoidt.h:34:1
'__anonymous_enum__::SEC_OID_TOTAL' from value '385' to '388' at secoidt.h:34:1
type of 'NSSCMSEnvelopedData* NSSCMSContentUnion::envelopedData' changed:
in pointed to type 'typedef NSSCMSEnvelopedData' at cmst.h:60:1:
underlying type 'struct NSSCMSEnvelopedDataStr' at cmst.h:257:1 changed:
type size hasn't changed
1 data member changes (2 filtered):
type of 'NSSCMSRecipientInfo** NSSCMSEnvelopedDataStr::recipientInfos' changed:
in pointed to type 'NSSCMSRecipientInfo*':
in pointed to type 'typedef NSSCMSRecipientInfo' at cmst.h:62:1:
underlying type 'struct NSSCMSRecipientInfoStr' at cmst.h:439:1 changed:
type size changed from 1536 to 1664 bits
3 data member changes:
type of '__anonymous_union__ NSSCMSRecipientInfoStr::ri' changed:
type size changed from 1344 to 1472 bits
2 data member changes:
type of 'NSSCMSKEKRecipientInfo __anonymous_union__::kekRecipientInfo' changed:
underlying type 'struct NSSCMSKEKRecipientInfoStr' at cmst.h:397:1 changed:
type size hasn't changed
1 data member change:
type of 'NSSCMSKEKIdentifier NSSCMSKEKRecipientInfoStr::kekIdentifier' changed:
underlying type 'struct NSSCMSKEKIdentifierStr' at cmst.h:390:1 changed:
type size hasn't changed
1 data member change:
type of 'SECItem* NSSCMSKEKIdentifierStr::other' changed:
in pointed to type 'typedef SECItem' at cmst.h:347:1:
underlying type 'struct SECItemStr' at cmst.h:342:1 changed:
type name changed from 'SECItemStr' to 'NSSCMSOtherKeyAttributeStr'
type size changed from 192 to 384 bits
2 data member deletions:
'unsigned char* SECItemStr::data', at offset 64 (in bits) at seccomon.h:52:1
'unsigned int SECItemStr::len', at offset 128 (in bits) at seccomon.h:53:1
1 data member insertion:
'SECItem NSSCMSOtherKeyAttributeStr::keyAttr', at offset 192 (in bits) at cmst.h:344:1
1 data member change:
type of 'SECItemType SECItemStr::type' changed:
underlying type 'enum __anonymous_enum__' at seccomon.h:50:1 changed:
entity changed from 'enum __anonymous_enum__' to 'struct SECItemStr' at seccomon.h:50:1
type size changed from 32 to 192 bits
type alignment changed from 32 to 0 bits
type of 'NSSCMSKeyAgreeRecipientInfo __anonymous_union__::keyAgreeRecipientInfo' changed:
underlying type 'struct NSSCMSKeyAgreeRecipientInfoStr' at cmst.h:376:1 changed:
type size changed from 1344 to 1472 bits
3 data member changes:
type of 'SECItem* NSSCMSKeyAgreeRecipientInfoStr::ukm' changed:
entity changed from 'SECItem*' to 'typedef SECItem' at seccomon.h:48:1
type size changed from 64 to 192 bits
'SECAlgorithmID NSSCMSKeyAgreeRecipientInfoStr::keyEncAlg' offset changed from 896 to 1024 (in bits) (by +128 bits)
'NSSCMSRecipientEncryptedKey** NSSCMSKeyAgreeRecipientInfoStr::recipientEncryptedKeys' offset changed from 1280 to 1408 (in bits) (by +128 bits)
'NSSCMSMessage* NSSCMSRecipientInfoStr::cmsg' offset changed from 1408 to 1536 (in bits) (by +128 bits)
'CERTCertificate* NSSCMSRecipientInfoStr::cert' offset changed from 1472 to 1600 (in bits) (by +128 bits)

View File

@ -1 +1 @@
NSS_3_99_BRANCH
NSS_3_100_BRANCH

View File

@ -1,50 +0,0 @@
# Minimal image with clang-format 3.9.
FROM ubuntu:bionic-20221215
LABEL maintainer="iaroslav.gridin@tuni.fi"
# for new clang/llvm
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
locales \
cmake \
build-essential \
git \
clang-10 \
mercurial \
unifdef \
python3-mako \
libgmp-dev \
jq \
python3-setuptools \
python3-pip \
python3-dev \
clang-format-10 \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get autoremove -y && apt-get clean -y
RUN pip3 install fastecdsa
ENV SHELL /bin/bash
ENV USER worker
ENV LOGNAME $USER
ENV HOME /home/$USER
ENV HOSTNAME taskcluster-worker
ENV LANG en_US.UTF-8
ENV LC_ALL $LANG
ENV HOST localhost
ENV DOMSUF localdomain
RUN locale-gen $LANG \
&& DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
RUN useradd -d $HOME -s $SHELL -m $USER
WORKDIR $HOME
ADD bin $HOME/bin
RUN chmod +x $HOME/bin/*
USER $USER
# Set a default command for debugging.
CMD ["/bin/bash", "--login"]

View File

@ -1,25 +0,0 @@
#!/usr/bin/env bash
set -v -e -x
if [ $(id -u) = 0 ]; then
# Drop privileges by re-running this script.
exec su worker $0
fi
# Default values for testing.
REVISION=${NSS_HEAD_REVISION:-default}
REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
# Clone NSS.
hg clone -r $REVISION $REPOSITORY nss
# Clone NSPR if needed.
hg clone -r default https://hg.mozilla.org/projects/nspr
if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
pushd nspr
cat ../nss/nspr.patch | patch -p1
popd
fi

View File

@ -1,10 +0,0 @@
#!/usr/bin/env bash
set -v -e -x
if [ $(id -u) = 0 ]; then
# Drop privileges by re-running this script.
exec su worker $0
fi
git clone --depth=1 https://gitlab.com/nisec/ecckiila.git

View File

@ -1,14 +0,0 @@
#!/bin/bash -eu
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
################################################################################
set -e -x -v
cd $HOME/ecckiila
cp $HOME/nss/.clang-format ./
for c in secp384r1 secp521r1; do (cd ecp/$c && cmake . && make && unifdef ecp_$c.c -DRIG_NULL -URIG_NSS -URIG_GOST -UOPENSSL_BUILDING_OPENSSL -UKIILA_OPENSSL_EMIT_CURVEDEF -UKIILA_UNUSED -UOPENSSL_NO_ASM -ULIB_TEST -x2 > tmp_ecp_$c.c && clang-format-10 -i tmp_ecp_$c.c && diff $HOME/nss/lib/freebl/ecl/ecp_$c.c tmp_ecp_$c.c); done;

View File

@ -19,6 +19,7 @@
"merge": "^1.2.0",
"minimist": "^1.2.0",
"slugid": "^1.1.0",
"tar": "^6.2.1",
"taskcluster-client": "^22.0.0"
}
}

View File

@ -16,6 +16,10 @@ function sha256(data) {
// Recursively collect a list of all files of a given directory.
function collectFilesInDirectory(dir) {
if (fs.lstatSync(dir).isFile()) {
return [dir];
}
return flatmap(fs.readdirSync(dir), entry => {
let entry_path = path.join(dir, entry);
@ -40,8 +44,8 @@ function collectFileHashes(context_path) {
// Compute a context hash for the given context path.
export default function (context_path) {
// Regenerate all images when the image_builder changes.
let hashes = collectFileHashes("automation/taskcluster/image_builder");
// Regenerate when image_builder.js changes
let hashes = collectFileHashes("automation/taskcluster/graph/src/image_builder.js");
// Regenerate images when the image itself changes.
hashes = hashes.concat(collectFileHashes(context_path));

View File

@ -20,11 +20,6 @@ const ACVP_IMAGE = {
path: "automation/taskcluster/docker-acvp"
};
const ECCKIILA_IMAGE = {
name: "ecckiila",
path: "automation/taskcluster/docker-ecckiila"
};
const CLANG_FORMAT_IMAGE = {
name: "clang-format",
path: "automation/taskcluster/docker-clang-format"
@ -1180,17 +1175,6 @@ async function scheduleTools() {
]
}));
queue.scheduleTask(merge(base, {
symbol: "ecckiila",
name: "ecckiila",
image: ECCKIILA_IMAGE,
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && bin/ecckiila.sh && bin/run.sh"
]
}));
queue.scheduleTask(merge(base, {
symbol: "Coverage",
name: "Coverage",

View File

@ -6,6 +6,9 @@ import * as queue from "./queue";
import context_hash from "./context_hash";
import taskcluster from "taskcluster-client";
const fs = require("fs");
const tar = require("tar");
async function taskHasImageArtifact(taskId) {
let queue = new taskcluster.Queue(taskcluster.fromEnvVars());
let {artifacts} = await queue.listLatestArtifacts(taskId);
@ -28,32 +31,37 @@ export async function findTask({name, path}) {
export async function buildTask({name, path}) {
let hash = await context_hash(path);
let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`;
let fullPath = "/home/worker/nss/" + path
let contextName = name + ".tar.gz";
let contextRoot = "/home/worker/docker-contexts/";
let contextPath = contextRoot + contextName;
if (!fs.existsSync(contextRoot)) {
fs.mkdirSync(contextRoot);
}
await tar.create({gzip: true, file: contextPath, cwd: fullPath}, ["."]);
return {
name: `Image Builder (${name})`,
image: "nssdev/image_builder:0.1.5",
image: "mozillareleases/image_builder:5.0.0",
workerType: "images-gcp",
routes: ["index." + ns],
env: {
NSS_HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
NSS_HEAD_REVISION: process.env.NSS_HEAD_REVISION,
PROJECT: process.env.TC_PROJECT,
CONTEXT_PATH: path,
IMAGE_NAME: name,
CONTEXT_PATH: "public/docker-contexts/" + contextName,
CONTEXT_TASK_ID: process.env.TASK_ID,
HASH: hash
},
artifacts: {
"public/image.tar.zst": {
type: "file",
expires: 24 * 90,
path: "/artifacts/image.tar.zst"
path: "/workspace/image.tar.zst"
}
},
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && nss/automation/taskcluster/scripts/build_image.sh"
],
platform: "nss-decision",
features: ["dind"],
features: ["allowPtrace", "chainOfTrust"],
maxRunTime: 7200,
kind: "build",
symbol: `I(${name})`

View File

@ -107,6 +107,10 @@ function convertTask(def) {
if (def.parents) {
dependencies = dependencies.concat(def.parents);
}
if (dependencies.length === 0) {
// If task has no dependencies, make it depend on the Decision task.
dependencies.push(process.env.TASK_ID);
}
if (def.tests) {
env.NSS_TESTS = def.tests;

View File

@ -57,7 +57,7 @@ function parseOptions(opts) {
}
// Parse tools.
let allTools = ["clang-format", "scan-build", "hacl", "acvp", "ecckiila", "saw", "abi", "coverage"];
let allTools = ["clang-format", "scan-build", "hacl", "acvp", "saw", "abi", "coverage"];
let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
// If the given value is "all" run all tools.

View File

@ -1,23 +0,0 @@
FROM ubuntu:16.04
MAINTAINER Tim Taubert <ttaubert@mozilla.com>
WORKDIR /home/worker
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y apt-transport-https apt-utils
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 && \
sh -c "echo deb https://get.docker.io/ubuntu docker main \
> /etc/apt/sources.list.d/docker.list"
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 41BD8711B1F0EC2B0D85B91CF59CE3A8323293EE && \
sh -c "echo deb http://ppa.launchpad.net/mercurial-ppa/releases/ubuntu xenial main \
> /etc/apt/sources.list.d/mercurial.list"
RUN apt-get update && apt-get install -y \
lxc-docker-1.6.1 \
mercurial
ADD bin /home/worker/bin
RUN chmod +x /home/worker/bin/*
# Set a default command useful for debugging
CMD ["/bin/bash", "--login"]

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -v -e -x
# Default values for testing.
REVISION=${NSS_HEAD_REVISION:-default}
REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
# Clone NSS.
for i in 0 2 5; do
sleep $i
hg clone -r $REVISION $REPOSITORY nss && exit 0
rm -rf nss
done
exit 1

View File

@ -1,27 +0,0 @@
#!/bin/bash -vex
set -x -e -v
# Prefix errors with taskcluster error prefix so that they are parsed by Treeherder
raise_error() {
echo
echo "[taskcluster-image-build:error] $1"
exit 1
}
# Ensure that the PROJECT is specified so the image can be indexed
test -n "$PROJECT" || raise_error "Project must be provided."
test -n "$HASH" || raise_error "Context Hash must be provided."
CONTEXT_PATH="/home/worker/nss/$CONTEXT_PATH"
test -d "$CONTEXT_PATH" || raise_error "Context Path $CONTEXT_PATH does not exist."
test -f "$CONTEXT_PATH/Dockerfile" || raise_error "Dockerfile must be present in $CONTEXT_PATH."
apt-get update
apt-get -y install zstd
docker build -t "$PROJECT:$HASH" "$CONTEXT_PATH"
mkdir /artifacts
docker save "$PROJECT:$HASH" | zstd > /artifacts/image.tar.zst

View File

@ -29,6 +29,7 @@ find . -type f -name '*.[ch]' -exec clang-format -i {} \+
# It was implemented like this due to not uniqueness of the names in the verified folders
# For instance, the files Hacl_Chacha20.h are present in both directories, but the content differs.
# TODO(Bug 1899443): remove these exceptions
files=($(find ~/nss/lib/freebl/verified/internal -type f -name '*.[ch]'))
for f in "${files[@]}"; do
file_name=$(basename "$f")
@ -37,7 +38,7 @@ for f in "${files[@]}"; do
-o $file_name == "Hacl_Ed25519_PrecompTable.h" ]
then
continue;
fi
fi
diff $hacl_file $f
done
@ -45,12 +46,11 @@ files=($(find ~/nss/lib/freebl/verified/ -type f -name '*.[ch]' -not -path "*/fr
for f in "${files[@]}"; do
file_name=$(basename "$f")
hacl_file=($(find ~/hacl-star/dist/mozilla/ ~/hacl-star/dist/karamel/ -type f -name $file_name -not -path "*/hacl-star/dist/mozilla/internal/*"))
# TODO(Bug 1854438): Remove P384 exception.
# TODO(Bug 1854439): Remove P521 exception.
if [ $file_name == "Hacl_P384.c" \
-o $file_name == "Hacl_P384.h" \
-o $file_name == "Hacl_P521.c" \
-o $file_name == "Hacl_P521.h" ]
-o $file_name == "Hacl_P521.h" \
-o $file_name == "target.h" ]
then
continue;
fi
@ -110,4 +110,4 @@ for f in "${files[@]}"; do
continue;
fi
diff $hacl_file $f
done
done

View File

@ -207,37 +207,20 @@ M_TimeOperation(void (*threadFunc)(void *),
}
/* Test curve using specific field arithmetic. */
#define ECTEST_NAMED_GFP(name_c, name_v) \
if (usefreebl) { \
printf("Testing %s using freebl implementation...\n", name_c); \
rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_GFp); \
if (rv != SECSuccess) \
goto cleanup; \
printf("... okay.\n"); \
} \
if (usepkcs11) { \
printf("Testing %s using pkcs11 implementation...\n", name_c); \
rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
if (rv != SECSuccess) \
goto cleanup; \
printf("... okay.\n"); \
}
/* Test curve using specific field arithmetic. */
#define ECTEST_NAMED_CUSTOM(name_c, name_v) \
if (usefreebl) { \
printf("Testing %s using freebl implementation...\n", name_c); \
rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_plain); \
if (rv != SECSuccess) \
goto cleanup; \
printf("... okay.\n"); \
} \
if (usepkcs11) { \
printf("Testing %s using pkcs11 implementation...\n", name_c); \
rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
if (rv != SECSuccess) \
goto cleanup; \
printf("... okay.\n"); \
#define ECTEST_NAMED(name_c, name_v) \
if (usefreebl) { \
printf("Testing %s using freebl implementation...\n", name_c); \
rv = ectest_curve_freebl(name_v, iterations, numThreads); \
if (rv != SECSuccess) \
goto cleanup; \
printf("... okay.\n"); \
} \
if (usepkcs11) { \
printf("Testing %s using pkcs11 implementation...\n", name_c); \
rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
if (rv != SECSuccess) \
goto cleanup; \
printf("... okay.\n"); \
}
#define PK11_SETATTRS(x, id, v, l) \
@ -455,8 +438,7 @@ ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
* If tests fail, then it prints an error message, aborts, and returns an
* error code. Otherwise, returns 0. */
SECStatus
ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
ECFieldType fieldType)
ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
{
ECParams ecParams = { 0 };
ECPrivateKey *ecPriv = NULL;
@ -620,10 +602,10 @@ main(int argv, char **argc)
/* specific arithmetic tests */
if (nist) {
ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
ECTEST_NAMED_CUSTOM("Curve25519", ECCurve25519);
ECTEST_NAMED("NIST-P256", ECCurve_NIST_P256);
ECTEST_NAMED("NIST-P384", ECCurve_NIST_P384);
ECTEST_NAMED("NIST-P521", ECCurve_NIST_P521);
ECTEST_NAMED("Curve25519", ECCurve25519);
}
cleanup:

View File

@ -20,14 +20,12 @@ typedef struct {
char *their_pubhex;
char *common_key;
char *name;
ECFieldType fieldType;
} ECDH_KAT;
typedef struct {
ECCurveName curve;
char *point;
char *name;
ECFieldType fieldType;
} ECDH_BAD;
#include "testvecs.h"
@ -49,8 +47,7 @@ printBuf(const SECItem *item)
/* Initialise test with basic curve populate with only the necessary things */
SECStatus
init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena,
ECFieldType type)
init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena)
{
if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
return SECFailure;
@ -69,7 +66,7 @@ init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena,
ecParams->DEREncoding.len = 0;
ecParams->arena = *arena;
ecParams->fieldID.size = ecCurve_map[curve]->size;
ecParams->fieldID.type = type;
ecParams->fieldID.type = ec_field_plain;
ecParams->cofactor = ecCurve_map[curve]->cofactor;
return SECSuccess;
@ -173,7 +170,7 @@ ectest_validate_point(ECDH_BAD *bad)
SECStatus rv = SECFailure;
PLArenaPool *arena = NULL;
rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
rv = init_params(&ecParams, bad->curve, &arena);
if (rv != SECSuccess) {
return rv;
}

View File

@ -4,175 +4,175 @@ static ECDH_KAT ecdh_testvecs[] = {
"04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
"04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
"46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
"curve: P256 vector: 0", ec_field_GFp },
"curve: P256 vector: 0" },
{ ECCurve_NIST_P256, 1,
"38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
"04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
"04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
"057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
"curve: P256 vector: 1", ec_field_GFp },
"curve: P256 vector: 1" },
{ ECCurve_NIST_P256, 1,
"1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
"04d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc",
"04a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
"2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
"curve: P256 vector: 2", ec_field_GFp },
"curve: P256 vector: 2" },
{ ECCurve_NIST_P256, 1,
"207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
"0424277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0dc4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
"04df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
"96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
"curve: P256 vector: 3", ec_field_GFp },
"curve: P256 vector: 3" },
{ ECCurve_NIST_P256, 1,
"59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
"04a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a",
"0441192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb9221af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
"19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
"curve: P256 vector: 4", ec_field_GFp },
"curve: P256 vector: 4" },
{ ECCurve_NIST_P256, 1,
"f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
"047b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a",
"0433e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
"664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
"curve: P256 vector: 5", ec_field_GFp },
"curve: P256 vector: 5" },
{ ECCurve_NIST_P256, 1,
"3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
"049fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0",
"046a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba740f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
"ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
"curve: P256 vector: 6", ec_field_GFp },
"curve: P256 vector: 6" },
{ ECCurve_NIST_P256, 1,
"d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
"0420f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa46de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5",
"04a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bbf6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
"35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
"curve: P256 vector: 7", ec_field_GFp },
"curve: P256 vector: 7" },
{ ECCurve_NIST_P256, 1,
"0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
"04abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6",
"0494e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
"605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
"curve: P256 vector: 8", ec_field_GFp },
"curve: P256 vector: 8" },
{ ECCurve_NIST_P256, 1,
"2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
"043d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a873950cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3",
"04e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274fd9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
"f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
"curve: P256 vector: 9", ec_field_GFp },
"curve: P256 vector: 9" },
{ ECCurve_NIST_P256, 1,
"77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
"04ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21",
"04f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff0165833bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
"8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
"curve: P256 vector: 10", ec_field_GFp },
"curve: P256 vector: 10" },
{ ECCurve_NIST_P256, 1,
"42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
"04ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb",
"042db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
"72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
"curve: P256 vector: 11", ec_field_GFp },
"curve: P256 vector: 11" },
{ ECCurve_NIST_P256, 1,
"ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
"049a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625dd07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62",
"04cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecbc3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
"e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
"curve: P256 vector: 12", ec_field_GFp },
"curve: P256 vector: 12" },
{ ECCurve_NIST_P256, 1,
"43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
"04f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb145eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d",
"0415b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
"ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
"curve: P256 vector: 13", ec_field_GFp },
"curve: P256 vector: 13" },
{ ECCurve_NIST_P256, 1,
"b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
"0469c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd",
"0449c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa18af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
"bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
"curve: P256 vector: 14", ec_field_GFp },
"curve: P256 vector: 14" },
{ ECCurve_NIST_P256, 1,
"4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
"045fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72",
"0419b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
"9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
"curve: P256 vector: 15", ec_field_GFp },
"curve: P256 vector: 15" },
{ ECCurve_NIST_P256, 1,
"4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
"04c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7cfbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321",
"042c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b0999546cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
"3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
"curve: P256 vector: 16", ec_field_GFp },
"curve: P256 vector: 16" },
{ ECCurve_NIST_P256, 1,
"1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
"0459e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37",
"04a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
"1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
"curve: P256 vector: 17", ec_field_GFp },
"curve: P256 vector: 17" },
{ ECCurve_NIST_P256, 1,
"dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
"0430b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb23146a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c",
"04a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
"430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
"curve: P256 vector: 18", ec_field_GFp },
"curve: P256 vector: 18" },
{ ECCurve_NIST_P256, 1,
"5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
"0446c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf639146c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86",
"04ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01fe9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
"1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
"curve: P256 vector: 19", ec_field_GFp },
"curve: P256 vector: 19" },
{ ECCurve_NIST_P256, 1,
"b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
"047c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0acc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1",
"04c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4ebf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
"4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
"curve: P256 vector: 20", ec_field_GFp },
"curve: P256 vector: 20" },
{ ECCurve_NIST_P256, 1,
"fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
"0438b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0",
"04317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb609420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
"30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
"curve: P256 vector: 21", ec_field_GFp },
"curve: P256 vector: 21" },
{ ECCurve_NIST_P256, 1,
"334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
"043f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca75212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06",
"0445fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb15c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
"2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
"curve: P256 vector: 22", ec_field_GFp },
"curve: P256 vector: 22" },
{ ECCurve_NIST_P256, 1,
"2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
"0429c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d",
"04a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
"2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
"curve: P256 vector: 23", ec_field_GFp },
"curve: P256 vector: 23" },
{ ECCurve_NIST_P256, 1,
"85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
"049cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d3337a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b",
"04356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
"1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
"curve: P256 vector: 24", ec_field_GFp },
"curve: P256 vector: 24" },
{ ECCurve_NIST_P384, 1,
"3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
@ -181,7 +181,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c5006"
"6ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a",
"5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
"curve: P384 vector: 0", ec_field_GFp },
"curve: P384 vector: 0" },
{ ECCurve_NIST_P384, 1,
"92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783",
@ -190,7 +190,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0"
"25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757",
"a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff",
"curve: P384 vector: 1", ec_field_GFp },
"curve: P384 vector: 1" },
{ ECCurve_NIST_P384, 1,
"12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853",
@ -199,7 +199,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"041aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180"
"419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3",
"3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435",
"curve: P384 vector: 2", ec_field_GFp },
"curve: P384 vector: 2" },
{ ECCurve_NIST_P384, 1,
"8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1",
@ -208,7 +208,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"048bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c44"
"9d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7",
"6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854",
"curve: P384 vector: 3", ec_field_GFp },
"curve: P384 vector: 3" },
{ ECCurve_NIST_P384, 1,
"84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f",
@ -217,7 +217,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b"
"0f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1",
"ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405",
"curve: P384 vector: 4", ec_field_GFp },
"curve: P384 vector: 4" },
{ ECCurve_NIST_P384, 1,
"68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b",
@ -226,7 +226,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c55388500"
"3e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345",
"ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec",
"curve: P384 vector: 5", ec_field_GFp },
"curve: P384 vector: 5" },
{ ECCurve_NIST_P384, 1,
"b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd",
@ -235,7 +235,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"043d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2"
"f9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71",
"1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b",
"curve: P384 vector: 6", ec_field_GFp },
"curve: P384 vector: 6" },
{ ECCurve_NIST_P384, 1,
"f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82",
@ -244,7 +244,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d"
"06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5",
"d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0",
"curve: P384 vector: 7", ec_field_GFp },
"curve: P384 vector: 7" },
{ ECCurve_NIST_P384, 1,
"9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2",
@ -253,7 +253,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"047cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a6"
"728c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e",
"bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104",
"curve: P384 vector: 8", ec_field_GFp },
"curve: P384 vector: 8" },
{ ECCurve_NIST_P384, 1,
"d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018",
@ -262,7 +262,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"048eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1b"
"a73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e",
"1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14",
"curve: P384 vector: 9", ec_field_GFp },
"curve: P384 vector: 9" },
{ ECCurve_NIST_P384, 1,
"83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b",
@ -271,7 +271,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f"
"14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68",
"1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9",
"curve: P384 vector: 10", ec_field_GFp },
"curve: P384 vector: 10" },
{ ECCurve_NIST_P384, 1,
"8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9",
@ -280,7 +280,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847"
"e34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c",
"6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954",
"curve: P384 vector: 11", ec_field_GFp },
"curve: P384 vector: 11" },
{ ECCurve_NIST_P384, 1,
"0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb",
@ -289,7 +289,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f"
"e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764",
"cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437",
"curve: P384 vector: 12", ec_field_GFp },
"curve: P384 vector: 12" },
{ ECCurve_NIST_P384, 1,
"037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4",
@ -298,7 +298,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"041c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3"
"bec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456",
"deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9",
"curve: P384 vector: 13", ec_field_GFp },
"curve: P384 vector: 13" },
{ ECCurve_NIST_P384, 1,
"e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991",
@ -307,7 +307,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1"
"a3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5",
"c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71",
"curve: P384 vector: 14", ec_field_GFp },
"curve: P384 vector: 14" },
{ ECCurve_NIST_P384, 1,
"f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791",
@ -316,7 +316,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"043497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a"
"a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316",
"d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e",
"curve: P384 vector: 15", ec_field_GFp },
"curve: P384 vector: 15" },
{ ECCurve_NIST_P384, 1,
"59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664",
@ -325,7 +325,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"0490a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240"
"9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e",
"32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1",
"curve: P384 vector: 16", ec_field_GFp },
"curve: P384 vector: 16" },
{ ECCurve_NIST_P384, 1,
"3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded",
@ -334,7 +334,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1"
"d15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f",
"1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1",
"curve: P384 vector: 17", ec_field_GFp },
"curve: P384 vector: 17" },
{ ECCurve_NIST_P384, 1,
"50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269",
@ -343,7 +343,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802"
"4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33",
"793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb",
"curve: P384 vector: 18", ec_field_GFp },
"curve: P384 vector: 18" },
{ ECCurve_NIST_P384, 1,
"06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064",
@ -352,7 +352,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf2"
"6d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9",
"012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8",
"curve: P384 vector: 19", ec_field_GFp },
"curve: P384 vector: 19" },
{ ECCurve_NIST_P384, 1,
"12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241",
@ -361,7 +361,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"0413741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1"
"b580baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586",
"ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98",
"curve: P384 vector: 20", ec_field_GFp },
"curve: P384 vector: 20" },
{ ECCurve_NIST_P384, 1,
"34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486",
@ -370,7 +370,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"049e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd44"
"46b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f",
"dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95",
"curve: P384 vector: 21", ec_field_GFp },
"curve: P384 vector: 21" },
{ ECCurve_NIST_P384, 1,
"dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c",
@ -379,7 +379,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"042db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5d"
"c022e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989",
"d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347",
"curve: P384 vector: 22", ec_field_GFp },
"curve: P384 vector: 22" },
{ ECCurve_NIST_P384, 1,
"6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce",
@ -388,7 +388,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"04329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d"
"3cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12",
"d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2",
"curve: P384 vector: 23", ec_field_GFp },
"curve: P384 vector: 23" },
{ ECCurve_NIST_P384, 1,
"74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8",
@ -397,7 +397,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"0429d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e3"
"9e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5",
"81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35",
"curve: P384 vector: 24", ec_field_GFp },
"curve: P384 vector: 24" },
{ ECCurve_NIST_P521, 1,
"017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743"
@ -410,7 +410,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
"005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9"
"759436a4d3c5bf6e74b9578fac148c831",
"curve: P521 vector: 0", ec_field_GFp },
"curve: P521 vector: 0" },
{ ECCurve_NIST_P521, 1,
"00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc"
@ -423,7 +423,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0",
"000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c2"
"6d42189273ca4efa4c3db6bd12a6853759",
"curve: P521 vector: 1", ec_field_GFp },
"curve: P521 vector: 1" },
{ ECCurve_NIST_P521, 1,
"012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b14"
@ -436,7 +436,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"60272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8",
"006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746"
"a10a3ad694daae00d980d944aabc6a08f",
"curve: P521 vector: 2", ec_field_GFp },
"curve: P521 vector: 2" },
{ ECCurve_NIST_P521, 1,
"00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e7"
@ -449,7 +449,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"3be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23",
"00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e"
"98bf1cec05e4beffb0591f97713c6",
"curve: P521 vector: 3", ec_field_GFp },
"curve: P521 vector: 3" },
{ ECCurve_NIST_P521, 1,
"01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72"
@ -462,7 +462,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e",
"0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb2"
"07bc1a6fb6cb6d467888dc044b3c",
"curve: P521 vector: 4", ec_field_GFp },
"curve: P521 vector: 4" },
{ ECCurve_NIST_P521, 1,
"009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33"
@ -475,7 +475,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94",
"005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d86101"
"6b6ad0c79805784c67f73ada96f351",
"curve: P521 vector: 5", ec_field_GFp },
"curve: P521 vector: 5" },
{ ECCurve_NIST_P521, 1,
"01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b"
@ -488,7 +488,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"7b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6",
"01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72"
"749f72cdceebe825e4b34ecd570",
"curve: P521 vector: 6", ec_field_GFp },
"curve: P521 vector: 6" },
{ ECCurve_NIST_P521, 1,
"00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b75885955"
@ -501,7 +501,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb",
"018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622"
"e9029e76dc6e3f0c69f7aeced565c2c",
"curve: P521 vector: 7", ec_field_GFp },
"curve: P521 vector: 7" },
{ ECCurve_NIST_P521, 1,
"0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a1"
@ -514,7 +514,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2",
"0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536"
"d6aa544dc7537a00c858f8b66319e25",
"curve: P521 vector: 8", ec_field_GFp },
"curve: P521 vector: 8" },
{ ECCurve_NIST_P521, 1,
"01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc81"
@ -527,7 +527,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb",
"004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7"
"a7f8c7befb611afe487ff032921f750f",
"curve: P521 vector: 9", ec_field_GFp },
"curve: P521 vector: 9" },
{ ECCurve_NIST_P521, 1,
"01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b"
@ -540,7 +540,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"3c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409",
"0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b05"
"94baa82ef8f244e6984ae87ae1ed124b7",
"curve: P521 vector: 10", ec_field_GFp },
"curve: P521 vector: 10" },
{ ECCurve_NIST_P521, 1,
"009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703a"
@ -553,7 +553,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"e15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf",
"017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c294"
"6c4b8abd1d56d620fab1b5ff1a3adc71f",
"curve: P521 vector: 11", ec_field_GFp },
"curve: P521 vector: 11" },
{ ECCurve_NIST_P521, 1,
"01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8"
@ -566,7 +566,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"c7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562",
"00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e30"
"4c24ddb1dedf1dd76de611fc4a2340336",
"curve: P521 vector: 12", ec_field_GFp },
"curve: P521 vector: 12" },
{ ECCurve_NIST_P521, 1,
"011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c"
@ -579,7 +579,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"2f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f",
"0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917"
"b0e76879e1011e51ccbd9f540c54d4f",
"curve: P521 vector: 13", ec_field_GFp },
"curve: P521 vector: 13" },
{ ECCurve_NIST_P521, 1,
"0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d"
@ -592,7 +592,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364",
"0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75a"
"f1ba519b2d31da33eda87a9d565748",
"curve: P521 vector: 14", ec_field_GFp },
"curve: P521 vector: 14" },
{ ECCurve_NIST_P521, 1,
"005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1"
@ -605,7 +605,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052",
"0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fc"
"fae69d689785e38c868eb4a27e7b",
"curve: P521 vector: 15", ec_field_GFp },
"curve: P521 vector: 15" },
{ ECCurve_NIST_P521, 1,
"008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40"
@ -618,7 +618,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb",
"00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b1"
"4bf9a6a70c439257199a640890b61d1",
"curve: P521 vector: 16", ec_field_GFp },
"curve: P521 vector: 16" },
{ ECCurve_NIST_P521, 1,
"0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074da"
@ -631,7 +631,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7",
"006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5c"
"b7076603b7bc38d432cbc059f80f9488",
"curve: P521 vector: 17", ec_field_GFp },
"curve: P521 vector: 17" },
{ ECCurve_NIST_P521, 1,
"011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610"
@ -644,7 +644,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20",
"01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f"
"146f0bbfb0683140403bfa4ccdb524a29",
"curve: P521 vector: 18", ec_field_GFp },
"curve: P521 vector: 18" },
{ ECCurve_NIST_P521, 1,
"010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c5"
@ -657,7 +657,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c",
"0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea895"
"4a8d0c8b851e81a56fda95212a6578f0e",
"curve: P521 vector: 19", ec_field_GFp },
"curve: P521 vector: 19" },
{ ECCurve_NIST_P521, 1,
"01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98"
@ -670,7 +670,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979",
"015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a8"
"0abafc106ef065c8f1c4e1119ef58d298b",
"curve: P521 vector: 20", ec_field_GFp },
"curve: P521 vector: 20" },
{ ECCurve_NIST_P521, 1,
"00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d9"
@ -683,7 +683,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923",
"014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44"
"f2153fb13506fa9cf43c9aab5750988c943",
"curve: P521 vector: 21", ec_field_GFp },
"curve: P521 vector: 21" },
{ ECCurve_NIST_P521, 1,
"00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0e"
@ -696,7 +696,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc",
"0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2"
"47e0da92f60d5b31f9e47672e57f710598f4",
"curve: P521 vector: 22", ec_field_GFp },
"curve: P521 vector: 22" },
{ ECCurve_NIST_P521, 1,
"005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e"
@ -709,7 +709,7 @@ static ECDH_KAT ecdh_testvecs[] = {
"8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb",
"00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca6"
"60d216c553622362794f7a2acc71022bdb16f",
"curve: P521 vector: 23", ec_field_GFp },
"curve: P521 vector: 23" },
{ ECCurve_NIST_P521, 1,
"00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471"
@ -722,9 +722,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46",
"01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a36"
"97062f42da237aa7f07e0af3fd00eb1800d9c41",
"curve: P521 vector: 24", ec_field_GFp },
"curve: P521 vector: 24" },
{ ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
{ ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL }
};
static ECDH_KAT nonnist_testvecs[] = {
@ -733,25 +733,25 @@ static ECDH_KAT nonnist_testvecs[] = {
NULL,
"e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
"c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
"curve: 25519 vector: 0", ec_field_plain },
"curve: 25519 vector: 0" },
{ ECCurve25519, 1,
"4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
NULL,
"e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
"95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
"curve: 25519 vector: 1", ec_field_plain },
"curve: 25519 vector: 1" },
{ ECCurve25519, 1,
"0900000000000000000000000000000000000000000000000000000000000000",
NULL,
"0900000000000000000000000000000000000000000000000000000000000000",
"422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
"curve: 25519 vector: 2", ec_field_plain },
"curve: 25519 vector: 2" },
{ ECCurve25519, 1000,
"0900000000000000000000000000000000000000000000000000000000000000",
NULL,
"0900000000000000000000000000000000000000000000000000000000000000",
"684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51",
"curve: 25519 vector: 1000 iterations", ec_field_plain },
"curve: 25519 vector: 1000 iterations" },
#ifdef NSS_ENABLE_EXPENSIVE_TESTS
/* This test is disabled by default because it takes a very long time
* to run. */
@ -760,59 +760,59 @@ static ECDH_KAT nonnist_testvecs[] = {
NULL,
"0900000000000000000000000000000000000000000000000000000000000000",
"7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
"curve: 25519 vector: 1000000 iterations", ec_field_plain },
"curve: 25519 vector: 1000000 iterations" },
#endif
{ ECCurve25519, 1,
"174a56a75017c029e0861044d3c57c291823cf477ae6e21065cc121578bfa893",
NULL,
"7bd8396462a5788951caf3d3a28cb0904e4d081e62e6ac2d9da7152eb1310f30",
"28c09f6be3666a6ab3bf8f5b03eec14e95505e32726ae887053ce6a2061a9656",
"curve: 25519 custom vector 1", ec_field_plain },
"curve: 25519 custom vector 1" },
{ ECCurve25519, 1,
"577a2a7fcdacd4ccf7d7f81ba93ec83ae4bda32bec00ff7d59c294b69404f688",
NULL,
"a43b5491cbd9273abf694115f383fabe3bdc5f2baa30d2e00e43b6937a75cc5d",
"4aed703c32552576ca0b30a3fab53242e1eea29ddec993219d3c2b3c3e59b735",
"curve: 25519 custom vector 1", ec_field_plain },
"curve: 25519 custom vector 1" },
{ ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
{ ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL }
};
static ECDH_BAD nonnist_testvecs_bad_values[] = {
{ ECCurve25519, "00", "curve: 25519 vector: 0 bad point", ec_field_plain },
{ ECCurve25519, "00", "curve: 25519 vector: 0 bad point" },
{ ECCurve25519,
"0100000000000000000000000000000000000000000000000000000000000000",
"curve: 25519 vector: 1 bad point", ec_field_plain },
"curve: 25519 vector: 1 bad point" },
{ ECCurve25519,
"e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b8",
"curve: 25519 vector: 2 bad point", ec_field_plain },
"curve: 25519 vector: 2 bad point" },
{ ECCurve25519,
"5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
"curve: 25519 vector: 3 bad point", ec_field_plain },
"curve: 25519 vector: 3 bad point" },
{ ECCurve25519,
"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"curve: 25519 vector: 4 bad point", ec_field_plain },
"curve: 25519 vector: 4 bad point" },
{ ECCurve25519,
"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"curve: 25519 vector: 5 bad point", ec_field_plain },
"curve: 25519 vector: 5 bad point" },
{ ECCurve25519,
"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"curve: 25519 vector: 6 bad point", ec_field_plain },
"curve: 25519 vector: 6 bad point" },
{ ECCurve25519,
"cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
"curve: 25519 vector: 7 bad point", ec_field_plain },
"curve: 25519 vector: 7 bad point" },
{ ECCurve25519,
"4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
"curve: 25519 vector: 8 bad point", ec_field_plain },
"curve: 25519 vector: 8 bad point" },
{ ECCurve25519,
"d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"curve: 25519 vector: 9 bad point", ec_field_plain },
"curve: 25519 vector: 9 bad point" },
{ ECCurve25519,
"daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"curve: 25519 vector: 10 bad point", ec_field_plain },
"curve: 25519 vector: 10 bad point" },
{ ECCurve25519,
"dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"curve: 25519 vector: 11 bad point", ec_field_plain },
"curve: 25519 vector: 11 bad point" },
{ ECCurve_pastLastCurve, 0, NULL, 0 }
{ ECCurve_pastLastCurve, 0, NULL }
};

View File

@ -1189,8 +1189,8 @@ const SEC_ASN1Template secuKDF2Params[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
{ SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
{ SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
{ SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
{ SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(secuPBEParams, keyLength) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL, offsetof(secuPBEParams, kdfAlg),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ 0 }
};
@ -1301,8 +1301,15 @@ secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
level + 1);
SECU_PrintInteger(out, &param.keyLength, "Key Length", level + 1);
SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF algorithm", level + 1);
if (param.keyLength.data != NULL) {
SECU_PrintInteger(out, &param.keyLength, "Key Length", level + 1);
}
if (param.kdfAlg.algorithm.data != NULL) {
SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF algorithm", level + 1);
} else {
SECU_Indent(out, level + 1);
fprintf(out, "Implicit KDF Algorithm: HMAC-SHA-1\n");
}
}
PORT_FreeArena(pool, PR_FALSE);
}

View File

@ -942,26 +942,16 @@ PKCS12U_MapHashFromString(char *hashString)
}
/* make sure it's a hashing oid */
if (HASH_GetHashTypeByOidTag(hashAlg) == HASH_AlgNULL) {
return SEC_OID_UNKNOWN;
/* allow HMAC here. HMAC implies PKCS 5 v2 pba */
SECOidTag baseHashAlg = HASH_GetHashOidTagByHMACOidTag(hashAlg);
if (baseHashAlg == SEC_OID_UNKNOWN) {
/* not an hmac either, reject the entry */
return SEC_OID_UNKNOWN;
}
}
return hashAlg;
}
static void
p12u_EnableAllCiphers()
{
SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
SEC_PKCS12SetPreferredCipher(PKCS12_AES_CBC_256, 1);
}
static PRUintn
P12U_Init(char *dir, char *dbprefix, PRBool listonly)
{
@ -983,7 +973,8 @@ P12U_Init(char *dir, char *dbprefix, PRBool listonly)
PORT_SetUCS2_ASCIIConversionFunction(p12u_ucs2_ascii_conversion_function);
/* use the defaults for UCS4-UTF8 and UCS2-UTF8 */
p12u_EnableAllCiphers();
/* ciphers are already enabled by default, allow policy to work */
/* p12u_EnableAllCiphers(); */
return 0;
}
@ -1174,6 +1165,10 @@ main(int argc, char **argv)
}
}
}
/* in FIPS mode default to encoding with pkcs5v2 for the MAC */
if (PK11_IsFIPS()) {
hash = SEC_OID_HMAC_SHA256;
}
if (pk12util.options[opt_Mac].activated) {
char *hashString = pk12util.options[opt_Mac].arg;

View File

@ -17,6 +17,7 @@
#include "nss.h"
#include "smime.h"
#include "pk11func.h"
#include "sechash.h"
#if defined(XP_UNIX)
#include <unistd.h>
@ -327,6 +328,15 @@ decode(FILE *out, SECItem *input, const struct decodeOptionsStr *decodeOptions)
fprintf(stderr, "signer %d status = %s\n", j, svs);
goto loser;
}
/* if the signatures validate and we asked to keep
* the certs, save the profiles */
if (decodeOptions->keepCerts) {
rv = NSS_SMIMESignerInfo_SaveSMIMEProfile(si);
if (rv != SECSuccess) {
SECU_PrintError(progName, "SMIME profile import failed");
goto loser;
}
}
}
} break;
case SEC_OID_PKCS7_ENVELOPED_DATA: {
@ -393,7 +403,7 @@ signed_data(struct signOptionsStr *signOptions)
NSSCMSMessage *cmsg = NULL;
NSSCMSContentInfo *cinfo;
NSSCMSSignedData *sigd;
NSSCMSSignerInfo *signerinfo;
NSSCMSSignerInfo *signerinfo = NULL;
CERTCertificate *cert = NULL, *ekpcert = NULL;
if (cms_verbose) {
@ -589,6 +599,7 @@ signed_data(struct signOptionsStr *signOptions)
fprintf(stderr, "ERROR: cannot add CMS signerInfo object.\n");
goto loser;
}
signerinfo = NULL; /* sigd has adopted signerinfo */
if (cms_verbose) {
fprintf(stderr, "created signed-data message\n");
}
@ -606,6 +617,9 @@ loser:
if (cert) {
CERT_DestroyCertificate(cert);
}
if (signerinfo) {
NSS_CMSSignerInfo_Destroy(signerinfo);
}
NSS_CMSMessage_Destroy(cmsg);
return NULL;
}
@ -1042,6 +1056,59 @@ doBatchDecode(FILE *outFile, PRFileDesc *batchFile,
return exitStatus;
}
/* legacy SHA2 table...
* cmsutil took hash values of SHA256, SHA244, etc., the the
* oid table has values of SHA-256, SHA-224. Use the follow
* table to handle the old values. NOTE: no need to add new
* hashes to this table, just use the actual oid table
* values */
typedef struct LegacyHashNameStr {
char *name;
SECOidTag tag;
} LegacyHashName;
LegacyHashName legacyHashNamesTable[] = {
{ "SHA1", SEC_OID_SHA1 },
{ "SHA224", SEC_OID_SHA224 },
{ "SHA256", SEC_OID_SHA256 },
{ "SHA384", SEC_OID_SHA384 },
{ "SHA512", SEC_OID_SHA512 },
};
size_t legacyHashNamesTableSize = PR_ARRAY_SIZE(legacyHashNamesTable);
SECOidTag
CMSU_FindTagFromString(const char *cipherString)
{
SECOidTag tag;
SECOidData *oid;
size_t slen;
/* future enhancement: accept dotted oid spec? */
for (tag = 1; (oid = SECOID_FindOIDByTag(tag)) != NULL; tag++) {
/* only interested in oids that we actually understand */
if (oid->mechanism == CKM_INVALID_MECHANISM) {
continue;
}
if (PORT_Strcasecmp(oid->desc, cipherString) != 0) {
continue;
}
return tag;
}
slen = PORT_Strlen(cipherString);
if ((slen > 3) && (PORT_Strncasecmp(cipherString, "SHA", 3) == 0) &&
(cipherString[3] != '-')) {
int i;
for (i = 0; i < legacyHashNamesTableSize; i++) {
if (PORT_Strcasecmp(legacyHashNamesTable[i].name, cipherString) == 0) {
return legacyHashNamesTable[i].tag;
}
}
/* not on any table, must be invalid */
}
return SEC_OID_UNKNOWN;
}
int
main(int argc, char **argv)
{
@ -1075,6 +1142,8 @@ main(int argc, char **argv)
PORT_Assert(ev);
#endif
SECOID_Init();
progName = strrchr(argv[0], '/');
if (!progName)
progName = strrchr(argv[0], '\\');
@ -1141,25 +1210,26 @@ main(int argc, char **argv)
exit(1);
}
decodeOptions.suppressContent = PR_TRUE;
if (!strcmp(optstate->value, "MD2"))
signOptions.hashAlgTag = SEC_OID_MD2;
else if (!strcmp(optstate->value, "MD4"))
signOptions.hashAlgTag = SEC_OID_MD4;
else if (!strcmp(optstate->value, "MD5"))
signOptions.hashAlgTag = SEC_OID_MD5;
else if (!strcmp(optstate->value, "SHA1"))
signOptions.hashAlgTag = SEC_OID_SHA1;
else if (!strcmp(optstate->value, "SHA256"))
signOptions.hashAlgTag = SEC_OID_SHA256;
else if (!strcmp(optstate->value, "SHA384"))
signOptions.hashAlgTag = SEC_OID_SHA384;
else if (!strcmp(optstate->value, "SHA512"))
signOptions.hashAlgTag = SEC_OID_SHA512;
else {
/* lookup hash value from our oid table and make sure it's a hash
* using HASH_ functions */
signOptions.hashAlgTag = CMSU_FindTagFromString(optstate->value);
if (HASH_GetHashTypeByOidTag(signOptions.hashAlgTag) == HASH_AlgNULL) {
char *comma = "";
int i;
/* it wasn't, use the HASH_ functions to find the valid values
* and print it as an error */
fprintf(stderr,
"%s: -H requires one of MD2,MD4,MD5,SHA1,SHA256,SHA384,SHA512\n",
progName);
exit(1);
"%s: -H requires one of ", progName);
for (i = HASH_AlgNULL + 1; PR_TRUE; i++) {
SECOidTag hashTag = HASH_GetHashOidTagByHashType(i);
if (hashTag == SEC_OID_UNKNOWN) {
fprintf(stderr, "\n");
exit(1);
}
fprintf(stderr, "%s%s", comma, SECOID_FindOIDTagDescription(hashTag));
comma = ",";
}
/* NOT REACHED */
}
break;
case 'N':

View File

@ -10,3 +10,4 @@
*/
#error "Do not include this header file."

View File

@ -115,7 +115,7 @@
<varlistentry>
<term>-M hashAlg</term>
<listitem><para>Specify the hash algorithm used in the pkcs #12 mac. This algorithm also specifies the HMAC used in the prf when using pkcs #5 v2.</para></listitem>
<listitem><para>Specify the hash algorithm used in the pkcs #12 mac. If an hmac is specified, then the PKCS #12 mac is replaced by a PKCS #5 mac1 pbe. This algorithm also specifies the HMAC used in the prf when using pkcs #5 v2.</para></listitem>
</varlistentry>

View File

@ -9,6 +9,9 @@
'variables': {
'debug_optimization_level': '2',
},
'cflags_cc': [
'-Wno-vla-extension',
],
'target_conditions': [
[ '_type=="executable"', {
'libraries!': [

View File

@ -61,3 +61,31 @@ TEST_F(pkixcheck_CheckIssuer, EmptyIssuer)
{
ASSERT_EQ(Result::ERROR_EMPTY_ISSUER_NAME, CheckIssuer(EMPTY_NAME));
}
TEST_F(pkixcheck_CheckIssuer, TrailingData)
{
static const uint8_t validNameData[] = {
0x30/*SEQUENCE*/, 0x02/*LENGTH=2*/,
0x31, 0x00 // the contents of the sequence aren't validated
};
static const Input validName(validNameData);
ASSERT_EQ(Success, CheckIssuer(validName));
static const uint8_t trailingDataData[] = {
0x30/*SEQUENCE*/, 0x02/*LENGTH=2*/,
0x31, 0x00, // the contents of the sequence aren't validated
0x77 // trailing data is invalid
};
static const Input trailingData(trailingDataData);
ASSERT_EQ(Result::ERROR_BAD_DER, CheckIssuer(trailingData));
}
TEST_F(pkixcheck_CheckIssuer, InvalidContents)
{
static const uint8_t invalidContentsData[] = {
0x31/*SET (should be SEQUENCE)*/, 0x02/*LENGTH=2*/,
0x31, 0x00
};
static const Input invalidContents(invalidContentsData);
ASSERT_EQ(Result::ERROR_BAD_DER, CheckIssuer(invalidContents));
}

View File

@ -282,3 +282,19 @@ TEST_F(pkixcheck_CheckKeyUsage, unusedBitNotZero)
ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA, &twoValueBytes,
KeyUsage::digitalSignature));
}
TEST_F(pkixcheck_CheckKeyUsage, trailingData)
{
static uint8_t keyUsageWithTrailingDataData[] = {
0x03/*BIT STRING*/, 0x02/*LENGTH=2*/, 7/*unused bits*/, 0x80,
// The BIT STRING has already ended, but there's trailing data
0xab, 0xba
};
static const Input keyUsageWithTrailingDataBytes(keyUsageWithTrailingDataData);
ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeEndEntity,
&keyUsageWithTrailingDataBytes,
KeyUsage::digitalSignature));
ASSERT_BAD(CheckKeyUsage(EndEntityOrCA::MustBeCA,
&keyUsageWithTrailingDataBytes,
KeyUsage::digitalSignature));
}

View File

@ -71,6 +71,11 @@ static const uint8_t zeroByteInteger[] = {
0x30, 0x02, 0x02, 0x00
};
static const uint8_t trailingData[] = {
0x30, 0x03, 0x02, 0x01, 0x05, // statusRequest
0xe5, 0xe5, 0xe5 // trailing data
};
static const TLSFeaturesTestParams
TLSFEATURESSATISFIED_TEST_PARAMS[] =
{
@ -87,6 +92,8 @@ static const TLSFeaturesTestParams
Result::ERROR_REQUIRED_TLS_FEATURE_MISSING },
{ BS(zeroByteInteger), Result::ERROR_REQUIRED_TLS_FEATURE_MISSING,
Result::ERROR_REQUIRED_TLS_FEATURE_MISSING },
{ BS(trailingData), Result::ERROR_BAD_DER,
Result::ERROR_REQUIRED_TLS_FEATURE_MISSING },
};
class pkixcheck_TLSFeaturesSatisfiedInternal

View File

@ -218,6 +218,7 @@ public:
/*optional*/ const ByteString* certs = nullptr,
/*optional*/ OCSPResponseExtension* singleExtensions = nullptr,
/*optional*/ OCSPResponseExtension* responseExtensions = nullptr,
/*optional*/ const ByteString* trailingResponseData = nullptr,
/*optional*/ DigestAlgorithm certIDHashAlgorithm = DigestAlgorithm::sha1,
/*optional*/ ByteString certIDHashAlgorithmEncoded = ByteString())
{
@ -236,6 +237,7 @@ public:
context.certs = certs;
context.singleExtensions = singleExtensions;
context.responseExtensions = responseExtensions;
context.trailingResponseData = trailingResponseData;
context.certStatus = static_cast<uint8_t>(certStatus);
context.thisUpdate = thisUpdate;
@ -430,17 +432,17 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, check_validThrough)
}
}
// python DottedOIDToCode.py --tlv
// id_ocsp_singleExtensionSctList 1.3.6.1.4.1.11129.2.4.5
static const uint8_t tlv_id_ocsp_singleExtensionSctList[] = {
0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x05
};
static const uint8_t dummySctList[] = {
0x01, 0x02, 0x03, 0x04, 0x05
};
TEST_F(pkixocsp_VerifyEncodedResponse_successful, ct_extension)
{
// python DottedOIDToCode.py --tlv
// id_ocsp_singleExtensionSctList 1.3.6.1.4.1.11129.2.4.5
static const uint8_t tlv_id_ocsp_singleExtensionSctList[] = {
0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x05
};
static const uint8_t dummySctList[] = {
0x01, 0x02, 0x03, 0x04, 0x05
};
OCSPResponseExtension ctExtension;
ctExtension.id = BytesToByteString(tlv_id_ocsp_singleExtensionSctList);
// SignedCertificateTimestampList structure is encoded as an OCTET STRING
@ -470,6 +472,35 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, ct_extension)
trustDomain.signedCertificateTimestamps);
}
TEST_F(pkixocsp_VerifyEncodedResponse_successful, trailingResponseData)
{
OCSPResponseExtension ctExtension;
ctExtension.id = BytesToByteString(tlv_id_ocsp_singleExtensionSctList);
// SignedCertificateTimestampList structure is encoded as an OCTET STRING
// within the extension value (see RFC 6962 section 3.3).
// pkix decodes it internally and returns the actual structure.
ctExtension.value = TLV(der::OCTET_STRING, BytesToByteString(dummySctList));
ByteString trailingResponseData(3, 0x20);
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID, byKey,
*rootKeyPair, oneDayBeforeNow,
oneDayBeforeNow, &oneDayAfterNow,
sha256WithRSAEncryption(),
/*certs*/ nullptr,
&ctExtension,
/*responseExtensions*/ nullptr,
&trailingResponseData));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_MALFORMED_RESPONSE,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
}
struct CertIDHashAlgorithm
{
DigestAlgorithm hashAlgorithm;
@ -519,6 +550,7 @@ TEST_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm, CertIDHashAlgorithm)
nullptr,
nullptr,
nullptr,
nullptr,
GetParam().hashAlgorithm,
GetParam().encodedHashAlgorithm));
Input response;

View File

@ -649,30 +649,26 @@ class TestAgent {
return SECSuccess;
}
static SECStatus certCompressionShrinkDecode(
const SECItem* input, SECItem* output,
size_t expectedLenDecodedCertificate) {
static SECStatus certCompressionShrinkDecode(const SECItem* input,
unsigned char* output,
size_t outputLen,
size_t* usedLen) {
if (input == NULL || input->data == NULL) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
return SECFailure;
}
if (output == NULL || output->data == NULL ||
output->len != input->len + 2) {
if (output == NULL || outputLen != input->len + 2) {
return SECFailure;
}
if (expectedLenDecodedCertificate != output->len) {
std::cerr << "Cannot decompress certificate message." << std::endl;
return SECFailure;
}
output->data[0] = 0;
output->data[1] = 0;
output[0] = 0;
output[1] = 0;
for (size_t i = 0; i < input->len; i++) {
output->data[i + 2] = input->data[i];
output[i + 2] = input->data[i];
}
*usedLen = outputLen;
return SECSuccess;
}
@ -704,9 +700,10 @@ class TestAgent {
return SECSuccess;
}
static SECStatus certCompressionExpandDecode(
const SECItem* input, SECItem* output,
size_t expectedLenDecodedCertificate) {
static SECStatus certCompressionExpandDecode(const SECItem* input,
unsigned char* output,
size_t outputLen,
size_t* usedLen) {
if (input == NULL || input->data == NULL) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
return SECFailure;
@ -718,8 +715,7 @@ class TestAgent {
return SECFailure;
}
if (output == NULL || output->data == NULL ||
output->len != input->len - 4) {
if (output == NULL || outputLen != input->len - 4) {
return SECFailure;
}
@ -730,14 +726,11 @@ class TestAgent {
return SECFailure;
}
if (expectedLenDecodedCertificate != output->len) {
std::cerr << "Cannot decompress certificate message." << std::endl;
return SECFailure;
for (size_t i = 0; i < outputLen; i++) {
output[i] = input->data[i + 4];
}
for (size_t i = 0; i < output->len; i++) {
output->data[i] = input->data[i + 4];
}
*usedLen = outputLen;
return SECSuccess;
}
@ -771,9 +764,10 @@ class TestAgent {
return SECSuccess;
}
static SECStatus certCompressionRandomDecode(
const SECItem* input, SECItem* output,
size_t expectedLenDecodedCertificate) {
static SECStatus certCompressionRandomDecode(const SECItem* input,
unsigned char* output,
size_t outputLen,
size_t* usedLen) {
if (input == NULL || input->data == NULL) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
return SECFailure;
@ -785,19 +779,15 @@ class TestAgent {
return SECFailure;
}
if (output == NULL || output->data == NULL ||
output->len != input->len - 1) {
if (output == NULL || outputLen != input->len - 1) {
return SECFailure;
}
if (expectedLenDecodedCertificate != output->len) {
std::cerr << "Cannot decompress certificate message." << std::endl;
return SECFailure;
for (size_t i = 0; i < outputLen; i++) {
output[i] = input->data[i + 1];
}
for (size_t i = 0; i < output->len; i++) {
output->data[i] = input->data[i + 1];
}
*usedLen = outputLen;
return SECSuccess;
}

View File

@ -74,20 +74,45 @@ static const Pkcs11EcdsaTestParams kEcdsaVectors[] = {
DataBuffer(kP256Data, sizeof(kP256Data)),
DataBuffer(kP256Signature, sizeof(kP256Signature))}},
{SEC_OID_SHA256,
{DataBuffer(kP256Pkcs8ZeroPad, sizeof(kP256Pkcs8ZeroPad)),
DataBuffer(kP256SpkiZeroPad, sizeof(kP256SpkiZeroPad)),
DataBuffer(kP256DataZeroPad, sizeof(kP256DataZeroPad)),
DataBuffer(kP256SignatureZeroPad, sizeof(kP256SignatureZeroPad))}},
{DataBuffer(kP256Pkcs8KeyLen30, sizeof(kP256Pkcs8KeyLen30)),
DataBuffer(kP256SpkiKeyLen, sizeof(kP256SpkiKeyLen)),
DataBuffer(kP256DataKeyLen, sizeof(kP256DataKeyLen)),
DataBuffer(kP256SignatureKeyLen, sizeof(kP256SignatureKeyLen))}},
{SEC_OID_SHA256,
{DataBuffer(kP256Pkcs8KeyLen33, sizeof(kP256Pkcs8KeyLen33)),
DataBuffer(kP256SpkiKeyLen, sizeof(kP256SpkiKeyLen)),
DataBuffer(kP256DataKeyLen, sizeof(kP256DataKeyLen)),
DataBuffer(kP256SignatureKeyLen, sizeof(kP256SignatureKeyLen))}},
{SEC_OID_SHA384,
{DataBuffer(kP384Pkcs8, sizeof(kP384Pkcs8)),
DataBuffer(kP384Spki, sizeof(kP384Spki)),
DataBuffer(kP384Data, sizeof(kP384Data)),
DataBuffer(kP384Signature, sizeof(kP384Signature))}},
{SEC_OID_SHA256,
{DataBuffer(kP384Pkcs8KeyLen46, sizeof(kP384Pkcs8KeyLen46)),
DataBuffer(kP384SpkiKeyLen, sizeof(kP384SpkiKeyLen)),
DataBuffer(kP384DataKeyLen, sizeof(kP384DataKeyLen)),
DataBuffer(kP384SignatureKeyLen, sizeof(kP384SignatureKeyLen))}},
{SEC_OID_SHA256,
{DataBuffer(kP384Pkcs8KeyLen49, sizeof(kP384Pkcs8KeyLen49)),
DataBuffer(kP384SpkiKeyLen, sizeof(kP384SpkiKeyLen)),
DataBuffer(kP384DataKeyLen, sizeof(kP384DataKeyLen)),
DataBuffer(kP384SignatureKeyLen, sizeof(kP384SignatureKeyLen))}},
{SEC_OID_SHA512,
{DataBuffer(kP521Pkcs8, sizeof(kP521Pkcs8)),
DataBuffer(kP521Spki, sizeof(kP521Spki)),
DataBuffer(kP521Data, sizeof(kP521Data)),
DataBuffer(kP521Signature, sizeof(kP521Signature))}}};
DataBuffer(kP521Signature, sizeof(kP521Signature))}},
{SEC_OID_SHA256,
{DataBuffer(kP521Pkcs8KeyLen64, sizeof(kP521Pkcs8KeyLen64)),
DataBuffer(kP521SpkiKeyLen, sizeof(kP521SpkiKeyLen)),
DataBuffer(kP521DataKeyLen, sizeof(kP521DataKeyLen)),
DataBuffer(kP521SignatureKeyLen, sizeof(kP521SignatureKeyLen))}},
{SEC_OID_SHA256,
{DataBuffer(kP521Pkcs8KeyLen67, sizeof(kP521Pkcs8KeyLen67)),
DataBuffer(kP521SpkiKeyLen, sizeof(kP521SpkiKeyLen)),
DataBuffer(kP521DataKeyLen, sizeof(kP521DataKeyLen)),
DataBuffer(kP521SignatureKeyLen, sizeof(kP521SignatureKeyLen))}}};
INSTANTIATE_TEST_SUITE_P(EcdsaSignVerify, Pkcs11EcdsaTest,
::testing::ValuesIn(kEcdsaVectors));
@ -326,4 +351,56 @@ INSTANTIATE_TEST_SUITE_P(Pkcs11EcdsaRoundtripTest, Pkcs11EcdsaRoundtripTest,
SEC_OID_SECG_EC_SECP521R1,
SEC_OID_CURVE25519));
class Pkcs11EcdsaUnpaddedSignatureTest
: public Pkcs11EcdsaTestBase,
public ::testing::WithParamInterface<Pkcs11EcdsaTestParams> {
public:
Pkcs11EcdsaUnpaddedSignatureTest()
: Pkcs11EcdsaTestBase(GetParam().hash_oid_) {}
};
static const Pkcs11EcdsaTestParams kEcdsaUnpaddedSignaturesVectors[] = {
{SEC_OID_SHA512,
{DataBuffer(NULL, 0),
DataBuffer(kP256SpkiUnpaddedSig, sizeof(kP256SpkiUnpaddedSig)),
DataBuffer(kP256DataUnpaddedSigLong, sizeof(kP256DataUnpaddedSigLong)),
DataBuffer(kP256SignatureUnpaddedSigLong,
sizeof(kP256SignatureUnpaddedSigLong))}},
{SEC_OID_SHA512,
{DataBuffer(NULL, 0),
DataBuffer(kP256SpkiUnpaddedSig, sizeof(kP256SpkiUnpaddedSig)),
DataBuffer(kP256DataUnpaddedSigShort, sizeof(kP256DataUnpaddedSigShort)),
DataBuffer(kP256SignatureUnpaddedSigShort,
sizeof(kP256SignatureUnpaddedSigShort))}},
{SEC_OID_SHA512,
{DataBuffer(NULL, 0),
DataBuffer(kP384SpkiUnpaddedSig, sizeof(kP384SpkiUnpaddedSig)),
DataBuffer(kP384DataUnpaddedSigLong, sizeof(kP384DataUnpaddedSigLong)),
DataBuffer(kP384SignatureUnpaddedSigLong,
sizeof(kP384SignatureUnpaddedSigLong))}},
{SEC_OID_SHA512,
{DataBuffer(NULL, 0),
DataBuffer(kP384SpkiUnpaddedSig, sizeof(kP384SpkiUnpaddedSig)),
DataBuffer(kP384DataUnpaddedSigShort, sizeof(kP384DataUnpaddedSigShort)),
DataBuffer(kP384SignatureUnpaddedSigShort,
sizeof(kP384SignatureUnpaddedSigShort))}},
{SEC_OID_SHA512,
{DataBuffer(NULL, 0),
DataBuffer(kP521SpkiUnpaddedSig, sizeof(kP521SpkiUnpaddedSig)),
DataBuffer(kP521DataUnpaddedSigLong, sizeof(kP521DataUnpaddedSigLong)),
DataBuffer(kP521SignatureUnpaddedSigLong,
sizeof(kP521SignatureUnpaddedSigLong))}},
{SEC_OID_SHA512,
{DataBuffer(NULL, 0),
DataBuffer(kP521SpkiUnpaddedSig, sizeof(kP521SpkiUnpaddedSig)),
DataBuffer(kP521DataUnpaddedSigShort, sizeof(kP521DataUnpaddedSigShort)),
DataBuffer(kP521SignatureUnpaddedSigShort,
sizeof(kP521SignatureUnpaddedSigShort))}}};
TEST_P(Pkcs11EcdsaUnpaddedSignatureTest, Verify) {
Verify(GetParam().sig_params_);
}
INSTANTIATE_TEST_SUITE_P(EcdsaVerifyUnpaddedSignatures,
Pkcs11EcdsaUnpaddedSignatureTest,
::testing::ValuesIn(kEcdsaUnpaddedSignaturesVectors));
} // namespace nss_test

View File

@ -130,37 +130,197 @@ const uint8_t kP521Signature[] = {
0xd8, 0xb8, 0xc3, 0x7f, 0xf0, 0x77, 0x7b, 0x1a, 0x20, 0xf8, 0xcc, 0xb1,
0xdc, 0xcc, 0x43, 0x99, 0x7f, 0x1e, 0xe0, 0xe4, 0x4d, 0xa4, 0xa6, 0x7a};
// ECDSA P256 test case with a leading zero in the private key
const uint8_t kP256Pkcs8ZeroPad[] = {
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
// ECDSA P256 key of length 30 with leading zeros stripped.
const uint8_t kP256Pkcs8KeyLen30[] = {
0x30, 0x81, 0x85, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
0x00, 0x16, 0x40, 0x71, 0x99, 0xe3, 0x07, 0xaa, 0xdc, 0x98, 0x0b, 0x21,
0x62, 0xce, 0x66, 0x1f, 0xe4, 0x1a, 0x86, 0x9a, 0x23, 0x33, 0xf6, 0x72,
0xb4, 0xa3, 0xdc, 0x3b, 0x50, 0xba, 0x20, 0xce, 0xa1, 0x44, 0x03, 0x42,
0x00, 0x04, 0x53, 0x11, 0x9a, 0x86, 0xa0, 0xc2, 0x99, 0x4f, 0xa6, 0xf8,
0x08, 0xf8, 0x61, 0x01, 0x0e, 0x6b, 0x04, 0x9c, 0xd8, 0x15, 0x63, 0x2e,
0xd1, 0x38, 0x00, 0x10, 0xee, 0xe4, 0xc9, 0x11, 0xff, 0x05, 0xba, 0xd6,
0xcd, 0x94, 0xea, 0x00, 0xec, 0x85, 0x26, 0x2c, 0xbd, 0x4d, 0x85, 0xbd,
0x20, 0xce, 0xa5, 0xb1, 0x3f, 0x4d, 0x82, 0x9b, 0x9f, 0x28, 0x2e, 0xd3,
0x8a, 0x87, 0x1f, 0x89, 0xf8, 0x02};
const uint8_t kP256SpkiZeroPad[] = {
0x03, 0x01, 0x07, 0x04, 0x6b, 0x30, 0x69, 0x02, 0x01, 0x01, 0x04, 0x1e,
0x7d, 0x75, 0x44, 0xaa, 0x3b, 0x34, 0x5e, 0x0e, 0x70, 0x99, 0x02, 0xd0,
0x2e, 0xed, 0x45, 0x98, 0x9f, 0x03, 0x37, 0x64, 0x03, 0xe4, 0x3a, 0x11,
0x73, 0xe5, 0x52, 0x0f, 0x5b, 0xf4, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
0x44, 0x4c, 0x75, 0xd3, 0xc9, 0x55, 0xdd, 0x5a, 0x3b, 0xa1, 0xfb, 0x91,
0xff, 0x74, 0x5f, 0x10, 0x8b, 0xe9, 0xd0, 0xad, 0x92, 0xf7, 0xd7, 0x66,
0x78, 0x63, 0xba, 0x9f, 0xca, 0x58, 0xcf, 0xd3, 0x94, 0x24, 0xb8, 0xf0,
0x86, 0x52, 0x45, 0xcb, 0xbb, 0x9e, 0x83, 0x28, 0x83, 0x1f, 0x1d, 0x29,
0x4b, 0xca, 0xe0, 0x8b, 0x8c, 0x61, 0x1c, 0x43, 0x61, 0xce, 0x93, 0xba,
0x1c, 0x44, 0xf1, 0xb0};
// ECDSA P256 key of length 33 with an extra leading zero.
// Arithmetically equivalent to kP256Pkcs8KeyLen30.
const uint8_t kP256Pkcs8KeyLen33[] = {
0x30, 0x81, 0x88, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0x04, 0x6e, 0x30, 0x6c, 0x02, 0x01, 0x01, 0x04, 0x21,
0x00, 0x00, 0x00, 0x7d, 0x75, 0x44, 0xaa, 0x3b, 0x34, 0x5e, 0x0e, 0x70,
0x99, 0x02, 0xd0, 0x2e, 0xed, 0x45, 0x98, 0x9f, 0x03, 0x37, 0x64, 0x03,
0xe4, 0x3a, 0x11, 0x73, 0xe5, 0x52, 0x0f, 0x5b, 0xf4, 0xa1, 0x44, 0x03,
0x42, 0x00, 0x04, 0x44, 0x4c, 0x75, 0xd3, 0xc9, 0x55, 0xdd, 0x5a, 0x3b,
0xa1, 0xfb, 0x91, 0xff, 0x74, 0x5f, 0x10, 0x8b, 0xe9, 0xd0, 0xad, 0x92,
0xf7, 0xd7, 0x66, 0x78, 0x63, 0xba, 0x9f, 0xca, 0x58, 0xcf, 0xd3, 0x94,
0x24, 0xb8, 0xf0, 0x86, 0x52, 0x45, 0xcb, 0xbb, 0x9e, 0x83, 0x28, 0x83,
0x1f, 0x1d, 0x29, 0x4b, 0xca, 0xe0, 0x8b, 0x8c, 0x61, 0x1c, 0x43, 0x61,
0xce, 0x93, 0xba, 0x1c, 0x44, 0xf1, 0xb0};
// SPKI for kP256Pkcs8KeyLen30 / kP256Pkcs8KeyLen33
const uint8_t kP256SpkiKeyLen[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04, 0x53, 0x11, 0x9a, 0x86, 0xa0, 0xc2, 0x99, 0x4f, 0xa6,
0xf8, 0x08, 0xf8, 0x61, 0x01, 0x0e, 0x6b, 0x04, 0x9c, 0xd8, 0x15, 0x63,
0x2e, 0xd1, 0x38, 0x00, 0x10, 0xee, 0xe4, 0xc9, 0x11, 0xff, 0x05, 0xba,
0xd6, 0xcd, 0x94, 0xea, 0x00, 0xec, 0x85, 0x26, 0x2c, 0xbd, 0x4d, 0x85,
0xbd, 0x20, 0xce, 0xa5, 0xb1, 0x3f, 0x4d, 0x82, 0x9b, 0x9f, 0x28, 0x2e,
0xd3, 0x8a, 0x87, 0x1f, 0x89, 0xf8, 0x02};
const uint8_t kP256DataZeroPad[] = {'s', 'a', 'm', 'p', 'l', 'e'};
const uint8_t kP256SignatureZeroPad[] = {
0xa6, 0xf4, 0xe4, 0xa8, 0x3f, 0x03, 0x59, 0x89, 0x60, 0x53, 0xe7,
0xdc, 0xb5, 0xbe, 0x78, 0xaf, 0xc1, 0xca, 0xc0, 0x65, 0xba, 0xa4,
0x3c, 0xf1, 0xe4, 0xae, 0xe3, 0xba, 0x22, 0x3d, 0xac, 0x9d, 0x6d,
0x1b, 0x26, 0x00, 0xcf, 0x47, 0xa1, 0xe1, 0x04, 0x21, 0x8d, 0x0b,
0xbb, 0x16, 0xfa, 0x3e, 0x59, 0x32, 0x01, 0xb0, 0x45, 0x3e, 0x27,
0xa4, 0xc4, 0xfd, 0x31, 0xc9, 0x1a, 0x8e, 0x74, 0xd8};
0x42, 0x00, 0x04, 0x44, 0x4c, 0x75, 0xd3, 0xc9, 0x55, 0xdd, 0x5a, 0x3b,
0xa1, 0xfb, 0x91, 0xff, 0x74, 0x5f, 0x10, 0x8b, 0xe9, 0xd0, 0xad, 0x92,
0xf7, 0xd7, 0x66, 0x78, 0x63, 0xba, 0x9f, 0xca, 0x58, 0xcf, 0xd3, 0x94,
0x24, 0xb8, 0xf0, 0x86, 0x52, 0x45, 0xcb, 0xbb, 0x9e, 0x83, 0x28, 0x83,
0x1f, 0x1d, 0x29, 0x4b, 0xca, 0xe0, 0x8b, 0x8c, 0x61, 0x1c, 0x43, 0x61,
0xce, 0x93, 0xba, 0x1c, 0x44, 0xf1, 0xb0};
// Signature from kP256Pkcs8KeyLen30 / kP256Pkcs8KeyLen33
const uint8_t kP256DataKeyLen[] = {'s', 'a', 'm', 'p', 'l', 'e'};
const uint8_t kP256SignatureKeyLen[] = {
0x40, 0x5f, 0x6f, 0x44, 0xc0, 0x94, 0xf8, 0xfd, 0xa0, 0xac, 0xb7,
0x25, 0x7b, 0x0e, 0x99, 0x33, 0x80, 0xfc, 0x5b, 0x37, 0xd6, 0xfa,
0x42, 0xb9, 0xfb, 0xd1, 0xdd, 0x0c, 0xfa, 0x3d, 0x01, 0x88, 0x42,
0x46, 0x28, 0x0c, 0xc9, 0x4f, 0xe7, 0x95, 0xd4, 0x88, 0x3b, 0x2f,
0x58, 0x23, 0x15, 0x1e, 0x44, 0xca, 0xab, 0x0b, 0x61, 0x32, 0x76,
0xe6, 0xab, 0x3e, 0xfd, 0x23, 0x86, 0xfd, 0xb6, 0x12,
};
// ECDSA P384 key of length 46 with leading zeros stripped.
const uint8_t kP384Pkcs8KeyLen46[] = {
0x30, 0x81, 0xb4, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
0x04, 0x81, 0x9c, 0x30, 0x81, 0x99, 0x02, 0x01, 0x01, 0x04, 0x2e, 0x92,
0x62, 0x5a, 0x47, 0x27, 0x34, 0xe3, 0x95, 0x93, 0x02, 0x44, 0xc0, 0x56,
0x8a, 0x5c, 0xaa, 0x0f, 0x51, 0xd0, 0xf2, 0xc1, 0xb5, 0x4f, 0xfd, 0x59,
0xbb, 0x6d, 0x7a, 0x81, 0x55, 0x55, 0xa0, 0xbb, 0x00, 0xcf, 0x4a, 0x3a,
0xca, 0xa0, 0xb6, 0xb3, 0xe6, 0x95, 0xa5, 0x73, 0xdc, 0xa1, 0x64, 0x03,
0x62, 0x00, 0x04, 0xb8, 0xcf, 0x04, 0xee, 0x4b, 0x18, 0xdf, 0xde, 0x02,
0x23, 0xd4, 0x82, 0x1b, 0x18, 0x92, 0xf7, 0x4e, 0x60, 0x72, 0xb4, 0x75,
0x47, 0x5c, 0xd2, 0x00, 0x87, 0x03, 0xfd, 0x6f, 0x89, 0x6f, 0x70, 0xea,
0x2e, 0xd3, 0xfb, 0x91, 0x90, 0xcf, 0x23, 0x55, 0x7d, 0xf5, 0x2b, 0xfa,
0x99, 0xd3, 0xb2, 0xbe, 0xb6, 0x48, 0x56, 0xe9, 0x7a, 0x59, 0xeb, 0x88,
0x2f, 0x4c, 0x1b, 0x65, 0xdd, 0x2e, 0xeb, 0x67, 0xfe, 0xf7, 0x96, 0x95,
0xa7, 0x19, 0xb4, 0x23, 0x12, 0xa0, 0xd6, 0xac, 0x2c, 0x0d, 0x66, 0x81,
0x2c, 0xf4, 0x95, 0x99, 0x7c, 0x27, 0x4b, 0xbb, 0xfb, 0xd1, 0x4c, 0x26,
0x57, 0xa7, 0xd4};
// ECDSA P384 key of length 49 with an extra leading zero.
// Arithmetically equivalent to kP384Pkcs8KeyLen46.
const uint8_t kP384Pkcs8KeyLen49[] = {
0x30, 0x81, 0xb7, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
0x04, 0x81, 0x9f, 0x30, 0x81, 0x9c, 0x02, 0x01, 0x01, 0x04, 0x31, 0x00,
0x00, 0x00, 0x92, 0x62, 0x5a, 0x47, 0x27, 0x34, 0xe3, 0x95, 0x93, 0x02,
0x44, 0xc0, 0x56, 0x8a, 0x5c, 0xaa, 0x0f, 0x51, 0xd0, 0xf2, 0xc1, 0xb5,
0x4f, 0xfd, 0x59, 0xbb, 0x6d, 0x7a, 0x81, 0x55, 0x55, 0xa0, 0xbb, 0x00,
0xcf, 0x4a, 0x3a, 0xca, 0xa0, 0xb6, 0xb3, 0xe6, 0x95, 0xa5, 0x73, 0xdc,
0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xb8, 0xcf, 0x04, 0xee, 0x4b, 0x18,
0xdf, 0xde, 0x02, 0x23, 0xd4, 0x82, 0x1b, 0x18, 0x92, 0xf7, 0x4e, 0x60,
0x72, 0xb4, 0x75, 0x47, 0x5c, 0xd2, 0x00, 0x87, 0x03, 0xfd, 0x6f, 0x89,
0x6f, 0x70, 0xea, 0x2e, 0xd3, 0xfb, 0x91, 0x90, 0xcf, 0x23, 0x55, 0x7d,
0xf5, 0x2b, 0xfa, 0x99, 0xd3, 0xb2, 0xbe, 0xb6, 0x48, 0x56, 0xe9, 0x7a,
0x59, 0xeb, 0x88, 0x2f, 0x4c, 0x1b, 0x65, 0xdd, 0x2e, 0xeb, 0x67, 0xfe,
0xf7, 0x96, 0x95, 0xa7, 0x19, 0xb4, 0x23, 0x12, 0xa0, 0xd6, 0xac, 0x2c,
0x0d, 0x66, 0x81, 0x2c, 0xf4, 0x95, 0x99, 0x7c, 0x27, 0x4b, 0xbb, 0xfb,
0xd1, 0x4c, 0x26, 0x57, 0xa7, 0xd4};
const uint8_t kP384SpkiKeyLen[] = {
0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04,
0xb8, 0xcf, 0x04, 0xee, 0x4b, 0x18, 0xdf, 0xde, 0x02, 0x23, 0xd4, 0x82,
0x1b, 0x18, 0x92, 0xf7, 0x4e, 0x60, 0x72, 0xb4, 0x75, 0x47, 0x5c, 0xd2,
0x00, 0x87, 0x03, 0xfd, 0x6f, 0x89, 0x6f, 0x70, 0xea, 0x2e, 0xd3, 0xfb,
0x91, 0x90, 0xcf, 0x23, 0x55, 0x7d, 0xf5, 0x2b, 0xfa, 0x99, 0xd3, 0xb2,
0xbe, 0xb6, 0x48, 0x56, 0xe9, 0x7a, 0x59, 0xeb, 0x88, 0x2f, 0x4c, 0x1b,
0x65, 0xdd, 0x2e, 0xeb, 0x67, 0xfe, 0xf7, 0x96, 0x95, 0xa7, 0x19, 0xb4,
0x23, 0x12, 0xa0, 0xd6, 0xac, 0x2c, 0x0d, 0x66, 0x81, 0x2c, 0xf4, 0x95,
0x99, 0x7c, 0x27, 0x4b, 0xbb, 0xfb, 0xd1, 0x4c, 0x26, 0x57, 0xa7, 0xd4,
};
const uint8_t kP384DataKeyLen[] = {'s', 'a', 'm', 'p', 'l', 'e'};
const uint8_t kP384SignatureKeyLen[] = {
0xd7, 0xb7, 0x2a, 0x78, 0x49, 0x7f, 0xe9, 0x27, 0x28, 0x2e, 0x4b, 0x84,
0x38, 0x6c, 0xfa, 0x50, 0xcf, 0x81, 0x9b, 0x18, 0x10, 0xf6, 0x72, 0xb6,
0xce, 0xe1, 0xf3, 0xab, 0xb0, 0x33, 0x93, 0xd8, 0x77, 0x51, 0xc7, 0x6c,
0x31, 0xf4, 0x09, 0x5b, 0xeb, 0xe0, 0x05, 0xac, 0x9f, 0x8e, 0xc9, 0xb0,
0xa5, 0xea, 0x0c, 0x85, 0xf3, 0x29, 0xb1, 0x0f, 0x08, 0xb1, 0x33, 0x06,
0xf0, 0x89, 0xe4, 0x51, 0x54, 0xed, 0x98, 0xf3, 0x83, 0x05, 0xa6, 0xa5,
0xd3, 0x1d, 0xef, 0xde, 0xab, 0x01, 0xea, 0x6e, 0x83, 0x31, 0xf1, 0x89,
0xb1, 0x13, 0x55, 0x7d, 0x18, 0xbd, 0xf0, 0xee, 0x91, 0x01, 0x11, 0x21,
};
// ECDSA P521 key of length 64 with leading zeros stripped.
const uint8_t kP521Pkcs8KeyLen64[] = {
0x30, 0x81, 0xec, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
0x04, 0x81, 0xd4, 0x30, 0x81, 0xd1, 0x02, 0x01, 0x01, 0x04, 0x40, 0xcf,
0x70, 0xc4, 0x84, 0x8c, 0x95, 0x94, 0x71, 0x19, 0x51, 0xf0, 0x1d, 0x72,
0xae, 0xd4, 0xc8, 0x25, 0xb1, 0x63, 0x96, 0x93, 0xab, 0x9f, 0x5e, 0x1c,
0xee, 0x2e, 0xd5, 0x98, 0x9d, 0x18, 0xe1, 0x1d, 0x10, 0x77, 0xbc, 0xfe,
0x82, 0xcb, 0x8a, 0x47, 0x6c, 0x8d, 0x87, 0x9e, 0x42, 0x9a, 0x3e, 0x4a,
0x95, 0x3b, 0x8c, 0x66, 0x7a, 0x17, 0x82, 0x17, 0x4f, 0x29, 0x56, 0x7b,
0xa2, 0xba, 0x84, 0xa1, 0x81, 0x89, 0x03, 0x81, 0x86, 0x00, 0x04, 0x00,
0x65, 0x92, 0x0a, 0xd7, 0xa2, 0x34, 0xad, 0xf7, 0x13, 0x8b, 0xee, 0x05,
0x61, 0xb9, 0xb4, 0x8f, 0xd4, 0x45, 0x69, 0xd9, 0x32, 0x94, 0x2f, 0xec,
0xff, 0xa6, 0x7a, 0xa9, 0x41, 0xa1, 0x82, 0x56, 0xd6, 0xe7, 0x3d, 0x65,
0xb9, 0x5a, 0x8c, 0xaf, 0x10, 0x93, 0x69, 0xe8, 0xdf, 0xc3, 0xb6, 0x99,
0x0d, 0xca, 0x75, 0xc8, 0x94, 0x68, 0x97, 0xed, 0x3e, 0xd1, 0x00, 0x24,
0x36, 0x71, 0xee, 0x39, 0xa4, 0x00, 0xb1, 0x8b, 0x5d, 0xf4, 0xe5, 0x71,
0x70, 0xec, 0x4f, 0x5d, 0x59, 0x03, 0x17, 0xbd, 0xa6, 0x23, 0x56, 0xcf,
0xb1, 0x82, 0x65, 0x04, 0xd7, 0x1a, 0x5c, 0x9e, 0x03, 0x73, 0xc6, 0x04,
0x2f, 0x68, 0xc8, 0xab, 0x61, 0x5a, 0x45, 0x93, 0x1c, 0xfe, 0x65, 0x75,
0x0e, 0x38, 0x23, 0x74, 0xbe, 0xa9, 0x80, 0xfe, 0x1b, 0x95, 0x14, 0xdc,
0x5e, 0xa0, 0xd8, 0x6e, 0x0c, 0x81, 0xc9, 0x6c, 0x20, 0x20, 0xc1};
// ECDSA P521 key of length 67 with an extra leading zero.
// Arithmetically equivalent to kP521Pkcs8KeyLen64.
const uint8_t kP521Pkcs8KeyLen67[] = {
0x30, 0x81, 0xef, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
0x04, 0x81, 0xd7, 0x30, 0x81, 0xd4, 0x02, 0x01, 0x01, 0x04, 0x43, 0x00,
0x00, 0x00, 0xcf, 0x70, 0xc4, 0x84, 0x8c, 0x95, 0x94, 0x71, 0x19, 0x51,
0xf0, 0x1d, 0x72, 0xae, 0xd4, 0xc8, 0x25, 0xb1, 0x63, 0x96, 0x93, 0xab,
0x9f, 0x5e, 0x1c, 0xee, 0x2e, 0xd5, 0x98, 0x9d, 0x18, 0xe1, 0x1d, 0x10,
0x77, 0xbc, 0xfe, 0x82, 0xcb, 0x8a, 0x47, 0x6c, 0x8d, 0x87, 0x9e, 0x42,
0x9a, 0x3e, 0x4a, 0x95, 0x3b, 0x8c, 0x66, 0x7a, 0x17, 0x82, 0x17, 0x4f,
0x29, 0x56, 0x7b, 0xa2, 0xba, 0x84, 0xa1, 0x81, 0x89, 0x03, 0x81, 0x86,
0x00, 0x04, 0x00, 0x65, 0x92, 0x0a, 0xd7, 0xa2, 0x34, 0xad, 0xf7, 0x13,
0x8b, 0xee, 0x05, 0x61, 0xb9, 0xb4, 0x8f, 0xd4, 0x45, 0x69, 0xd9, 0x32,
0x94, 0x2f, 0xec, 0xff, 0xa6, 0x7a, 0xa9, 0x41, 0xa1, 0x82, 0x56, 0xd6,
0xe7, 0x3d, 0x65, 0xb9, 0x5a, 0x8c, 0xaf, 0x10, 0x93, 0x69, 0xe8, 0xdf,
0xc3, 0xb6, 0x99, 0x0d, 0xca, 0x75, 0xc8, 0x94, 0x68, 0x97, 0xed, 0x3e,
0xd1, 0x00, 0x24, 0x36, 0x71, 0xee, 0x39, 0xa4, 0x00, 0xb1, 0x8b, 0x5d,
0xf4, 0xe5, 0x71, 0x70, 0xec, 0x4f, 0x5d, 0x59, 0x03, 0x17, 0xbd, 0xa6,
0x23, 0x56, 0xcf, 0xb1, 0x82, 0x65, 0x04, 0xd7, 0x1a, 0x5c, 0x9e, 0x03,
0x73, 0xc6, 0x04, 0x2f, 0x68, 0xc8, 0xab, 0x61, 0x5a, 0x45, 0x93, 0x1c,
0xfe, 0x65, 0x75, 0x0e, 0x38, 0x23, 0x74, 0xbe, 0xa9, 0x80, 0xfe, 0x1b,
0x95, 0x14, 0xdc, 0x5e, 0xa0, 0xd8, 0x6e, 0x0c, 0x81, 0xc9, 0x6c, 0x20,
0x20, 0xc1};
const uint8_t kP521SpkiKeyLen[] = {
0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86,
0x00, 0x04, 0x00, 0x65, 0x92, 0x0a, 0xd7, 0xa2, 0x34, 0xad, 0xf7, 0x13,
0x8b, 0xee, 0x05, 0x61, 0xb9, 0xb4, 0x8f, 0xd4, 0x45, 0x69, 0xd9, 0x32,
0x94, 0x2f, 0xec, 0xff, 0xa6, 0x7a, 0xa9, 0x41, 0xa1, 0x82, 0x56, 0xd6,
0xe7, 0x3d, 0x65, 0xb9, 0x5a, 0x8c, 0xaf, 0x10, 0x93, 0x69, 0xe8, 0xdf,
0xc3, 0xb6, 0x99, 0x0d, 0xca, 0x75, 0xc8, 0x94, 0x68, 0x97, 0xed, 0x3e,
0xd1, 0x00, 0x24, 0x36, 0x71, 0xee, 0x39, 0xa4, 0x00, 0xb1, 0x8b, 0x5d,
0xf4, 0xe5, 0x71, 0x70, 0xec, 0x4f, 0x5d, 0x59, 0x03, 0x17, 0xbd, 0xa6,
0x23, 0x56, 0xcf, 0xb1, 0x82, 0x65, 0x04, 0xd7, 0x1a, 0x5c, 0x9e, 0x03,
0x73, 0xc6, 0x04, 0x2f, 0x68, 0xc8, 0xab, 0x61, 0x5a, 0x45, 0x93, 0x1c,
0xfe, 0x65, 0x75, 0x0e, 0x38, 0x23, 0x74, 0xbe, 0xa9, 0x80, 0xfe, 0x1b,
0x95, 0x14, 0xdc, 0x5e, 0xa0, 0xd8, 0x6e, 0x0c, 0x81, 0xc9, 0x6c, 0x20,
0x20, 0xc1,
};
const uint8_t kP521DataKeyLen[] = {'s', 'a', 'm', 'p', 'l', 'e'};
const uint8_t kP521SignatureKeyLen[] = {
0x00, 0x9e, 0x46, 0x74, 0xb3, 0xba, 0x40, 0x54, 0x96, 0xf7, 0xbe, 0xe6,
0x16, 0x1f, 0xb4, 0xd5, 0x35, 0x9b, 0xa7, 0xd3, 0x38, 0x80, 0x35, 0x81,
0x7e, 0x9e, 0xcd, 0xf5, 0x2a, 0xa5, 0xe5, 0x4c, 0x6d, 0xde, 0x80, 0x39,
0x28, 0x06, 0x07, 0x27, 0x91, 0x90, 0xb9, 0xd4, 0x7c, 0x18, 0x1e, 0x9a,
0x8f, 0x9e, 0xe4, 0xc8, 0xcb, 0x54, 0x36, 0x68, 0xee, 0x81, 0xa4, 0xef,
0x0b, 0x15, 0x7e, 0xc8, 0xc9, 0xbe, 0x01, 0x1a, 0x87, 0xaa, 0x50, 0xd0,
0x08, 0xd9, 0xb8, 0x3a, 0xec, 0xa5, 0xd8, 0x7c, 0x69, 0x90, 0xc1, 0x03,
0xeb, 0xe3, 0x1d, 0x3a, 0x76, 0x14, 0x82, 0xda, 0xd1, 0x1d, 0x36, 0x9d,
0x3a, 0x46, 0x34, 0xe7, 0x64, 0x78, 0x53, 0xa3, 0x71, 0x2b, 0xa1, 0x99,
0xe8, 0x9e, 0xe5, 0x45, 0x64, 0x1b, 0xc1, 0x04, 0x46, 0xe2, 0xd6, 0xf1,
0xfc, 0x11, 0x85, 0xe2, 0x38, 0x6d, 0x36, 0x26, 0x31, 0x58, 0x9a, 0x9d,
};
// ECDSA test vectors, SPKI and PKCS#8 edge cases.
const uint8_t kP256Pkcs8NoCurveOIDOrAlgorithmParams[] = {
@ -280,4 +440,110 @@ const uint8_t kP256SpkiPointNotOnCurve[] = {
0x28, 0xbc, 0x64, 0xf2, 0xf1, 0xb2, 0x0c, 0x2d, 0x7e, 0x9f, 0x51, 0x77,
0xa3, 0xc2, 0x94, 0x00, 0x33, 0x11, 0x77};
const uint8_t kP521DataUnpaddedSigLong[] = {'W', 'T', 'F', '6', '0',
'M', 'W', 'M', 'N', '3'};
const uint8_t kP521DataUnpaddedSigShort[] = {
'M', 'I', '6', '3', 'V', 'N', 'G', 'L', 'F', 'R',
};
const uint8_t kP521SpkiUnpaddedSig[] = {
0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86,
0x00, 0x04, 0x01, 0xd2, 0x37, 0xeb, 0x78, 0xc7, 0x9b, 0x86, 0xff, 0x29,
0x7b, 0x55, 0x4d, 0x11, 0xc7, 0x9c, 0x2d, 0xc1, 0x67, 0x9f, 0xad, 0x2a,
0xa9, 0xb9, 0x51, 0x30, 0x6d, 0xde, 0x14, 0x16, 0xea, 0xb3, 0x9d, 0x18,
0xfc, 0xf0, 0x38, 0x6e, 0x7f, 0xa6, 0x82, 0xb9, 0x19, 0x01, 0xaf, 0xe7,
0xc3, 0xd8, 0xec, 0x9a, 0x62, 0x7b, 0xbf, 0x41, 0xc7, 0x86, 0x89, 0x52,
0x76, 0x8e, 0x01, 0x97, 0x1b, 0x16, 0x97, 0x69, 0x01, 0x2d, 0x07, 0x88,
0x6f, 0xe0, 0x17, 0xbe, 0x82, 0xc4, 0x12, 0xd6, 0x16, 0x72, 0xf8, 0x57,
0x75, 0x5c, 0x69, 0x79, 0xd0, 0x11, 0x05, 0x96, 0x2f, 0xa4, 0x61, 0xcd,
0x8f, 0x54, 0x95, 0x58, 0xbd, 0x7d, 0x71, 0x84, 0x63, 0x18, 0xb8, 0x5b,
0xaa, 0x1b, 0xd2, 0xe9, 0x65, 0x63, 0x15, 0x34, 0x25, 0x35, 0x2f, 0x35,
0x27, 0x3a, 0x84, 0x42, 0x7a, 0x42, 0x8e, 0xfd, 0x15, 0xbe, 0x0c, 0x0c,
0xe2, 0x9f};
const uint8_t kP521SignatureUnpaddedSigLong[] = {
0x01, 0xa7, 0x3a, 0x14, 0x79, 0x77, 0x9e, 0x48, 0xb0, 0xff, 0xb5, 0xbe,
0xfb, 0xfa, 0x7a, 0x84, 0x24, 0xb3, 0x5c, 0xf0, 0xfd, 0x77, 0x9d, 0xd4,
0x66, 0x49, 0xfd, 0xbf, 0x04, 0xbf, 0xbb, 0x75, 0x22, 0xbb, 0x35, 0x42,
0xdb, 0xe7, 0xed, 0x5a, 0x8f, 0x15, 0xf3, 0xa9, 0x0e, 0xb6, 0x5b, 0xde,
0x23, 0x79, 0x47, 0xa7, 0x1d, 0x25, 0x24, 0x68, 0x63, 0xf6, 0x9c, 0x2e,
0x21, 0xe0, 0x30, 0xfc, 0xd3, 0x65, 0x01, 0x12, 0x4e, 0xf0, 0xbb, 0x89,
0xec, 0xec, 0x4f, 0xef, 0xbe, 0xdc, 0xd6, 0xac, 0xa4, 0x16, 0x68, 0x2b,
0x78, 0xdf, 0x6c, 0x6e, 0xb8, 0xf4, 0x5b, 0x45, 0x1b, 0xdd, 0x84, 0x40,
0x94, 0x07, 0xc7, 0xbc, 0xb6, 0x57, 0x92, 0xf1, 0x64, 0xb9, 0x2c, 0xcb,
0x1d, 0xbe, 0x1c, 0x93, 0x78, 0x97, 0x8b, 0x84, 0x4e, 0x69, 0x6d, 0x0b,
0xb0, 0x5f, 0xf1, 0x84, 0x18, 0x82, 0x8d, 0x55, 0xdf, 0x36, 0x43, 0x8a};
const uint8_t kP521SignatureUnpaddedSigShort[] = {
0x40, 0x12, 0xa7, 0x96, 0x5d, 0x77, 0xba, 0x8a, 0x90, 0x57, 0x52, 0x11,
0xad, 0x72, 0x21, 0xd6, 0x6c, 0x73, 0x81, 0x43, 0x5d, 0x09, 0xe4, 0xde,
0xee, 0xc2, 0xb5, 0x03, 0x1f, 0x0f, 0xd1, 0x6a, 0xfc, 0x26, 0x6d, 0x99,
0x6d, 0x84, 0x32, 0x05, 0x56, 0x66, 0xe3, 0x6b, 0xf7, 0xf2, 0x04, 0xc9,
0x44, 0x17, 0xaa, 0xbd, 0x24, 0xd8, 0x87, 0x4e, 0x53, 0x9d, 0x08, 0x65,
0x91, 0x95, 0xeb, 0xeb, 0x92, 0x0b, 0xdb, 0x34, 0x80, 0xe8, 0x9f, 0x38,
0x73, 0x00, 0x7c, 0xfc, 0x2b, 0xfa, 0xcf, 0xa6, 0x6c, 0x1c, 0xb0, 0x75,
0x76, 0x01, 0x22, 0xe7, 0x3c, 0xd8, 0xc4, 0x1f, 0x5e, 0xde, 0x0b, 0x95,
0x7a, 0x50, 0x2b, 0x8c, 0x87, 0xc4, 0x12, 0x8e, 0x00, 0x09, 0x29, 0x2c,
0x21, 0xd1, 0x96, 0xa0, 0xf3, 0x0f, 0x54, 0xdb, 0x6a, 0xbb, 0x90, 0xf5,
0x5c, 0x7a, 0x8d, 0x83, 0x9c, 0x39, 0x38, 0x58, 0x5a, 0x0e};
const uint8_t kP384DataUnpaddedSigLong[] = {'L', 'T', 'N', '4', 'B',
'P', 'X', 'Y', '5', 'N'};
const uint8_t kP384DataUnpaddedSigShort[] = {'3', 'U', 'S', 'N', 'N',
'U', '6', 'E', 'E', '0'};
const uint8_t kP384SpkiUnpaddedSig[] = {
0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04,
0x1e, 0x98, 0x4c, 0xcf, 0x05, 0xd4, 0x9b, 0x98, 0x11, 0xae, 0xa1, 0xaa,
0x72, 0x27, 0xac, 0xde, 0x7f, 0xe8, 0x4d, 0xda, 0xaa, 0x67, 0x51, 0x2e,
0x0b, 0x30, 0x31, 0xab, 0x05, 0xac, 0x95, 0xdf, 0x09, 0x96, 0xcf, 0xe3,
0xf5, 0xfa, 0x30, 0xad, 0x43, 0x0b, 0xa5, 0x7e, 0xd7, 0xd1, 0xee, 0x4e,
0x83, 0x53, 0xe3, 0x26, 0xeb, 0xc1, 0xc9, 0xe5, 0x35, 0x36, 0x1a, 0xbf,
0xbf, 0x99, 0xd6, 0xe2, 0x14, 0x43, 0xcb, 0x54, 0xde, 0x06, 0xb5, 0x7d,
0x27, 0xb7, 0xc2, 0x27, 0xaf, 0xb6, 0x12, 0x4f, 0x47, 0xa0, 0xdb, 0xb5,
0x6e, 0x7b, 0x44, 0x0d, 0xc8, 0xbd, 0x13, 0x3c, 0x27, 0x7c, 0xf2, 0x3a};
const uint8_t kP384SignatureUnpaddedSigLong[] = {
0x19, 0x22, 0x21, 0x72, 0x8a, 0xa4, 0x22, 0x26, 0x75, 0x16, 0x9c, 0x58,
0x93, 0xd8, 0x43, 0xac, 0x28, 0x78, 0xe7, 0xe2, 0xf2, 0x5d, 0xa6, 0x59,
0x74, 0x6d, 0x55, 0x95, 0xe1, 0xa8, 0xc9, 0x18, 0x54, 0x5d, 0x03, 0xa0,
0xb0, 0x90, 0xe9, 0xf1, 0xc5, 0xf6, 0x29, 0x1a, 0x50, 0x9d, 0xe3, 0xde,
0x4a, 0x69, 0xdf, 0x1b, 0xe5, 0x53, 0xd7, 0xe8, 0xd4, 0xbf, 0x8c, 0xfc,
0x07, 0x66, 0xbc, 0xa7, 0xb5, 0x47, 0x29, 0xbd, 0x15, 0x8c, 0x57, 0x6c,
0xde, 0x37, 0x57, 0xa4, 0xd4, 0x61, 0x79, 0x92, 0x67, 0x25, 0x2e, 0xbc,
0x8b, 0x88, 0x6a, 0xfa, 0xa5, 0x00, 0x19, 0x11, 0x64, 0x69, 0x7b, 0xf6};
const uint8_t kP384SignatureUnpaddedSigShort[] = {
0x69, 0xe6, 0xc2, 0xd0, 0xb0, 0x59, 0xca, 0x1f, 0x07, 0x4c, 0x90, 0x13,
0x75, 0xe0, 0xc5, 0xb9, 0x38, 0xf2, 0xd8, 0x55, 0xf7, 0x08, 0xbd, 0x8e,
0x61, 0xbd, 0x50, 0x7e, 0xb6, 0xb5, 0xea, 0xbc, 0xa4, 0xa0, 0x18, 0x9b,
0x63, 0x6b, 0x8a, 0x91, 0x88, 0x39, 0x0a, 0xbe, 0x6a, 0xb6, 0x4b, 0xaf,
0xcb, 0x31, 0x89, 0xcf, 0x43, 0x28, 0x4b, 0x04, 0x6a, 0xe0, 0x8d, 0xbc,
0xbf, 0xa2, 0x45, 0xdf, 0x1c, 0x83, 0x82, 0x3e, 0x2b, 0xa3, 0xea, 0x50,
0x80, 0xec, 0x31, 0x48, 0x20, 0x30, 0x75, 0x94, 0xd9, 0x08, 0x9f, 0x6f,
0x53, 0x21, 0x6f, 0x72, 0x74, 0x0c, 0xc4, 0x21, 0x28, 0xc9};
const uint8_t kP256DataUnpaddedSigLong[] = {'J', '5', 'C', 'N', 'Q',
'T', 'F', 'A', 'J', 'T'};
const uint8_t kP256DataUnpaddedSigShort[] = {'K', 'O', 'S', '9', '4',
'F', 'V', 'C', 'Y', 'C'};
const uint8_t kP256SpkiUnpaddedSig[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04, 0x30, 0x40, 0x9d, 0x57, 0xdd, 0xd0, 0x70, 0x1d, 0x4b,
0x40, 0x84, 0xd4, 0x7a, 0xc0, 0x30, 0x68, 0x33, 0xf1, 0x1d, 0x47, 0xaa,
0x37, 0x4d, 0xe2, 0xc8, 0xce, 0xdc, 0x82, 0x1d, 0xf7, 0xcf, 0xdd, 0x9e,
0xb6, 0x6c, 0x85, 0x87, 0x9d, 0x31, 0x79, 0x7e, 0xe4, 0xe9, 0xc7, 0x4f,
0xd6, 0x07, 0x1d, 0x2f, 0x54, 0x82, 0x5d, 0x22, 0xbf, 0xbc, 0xf0, 0x75,
0x01, 0x09, 0x43, 0xc6, 0x52, 0xcb, 0x45};
const uint8_t kP256SignatureUnpaddedSigLong[] = {
0xad, 0x6f, 0xcf, 0x41, 0xc1, 0x83, 0xe3, 0x6f, 0xe0, 0x2c, 0x9f,
0x56, 0xa5, 0x17, 0x60, 0xbf, 0x80, 0x71, 0x18, 0x54, 0x1d, 0x82,
0xdb, 0xe6, 0xc2, 0x4e, 0x60, 0x4a, 0xa6, 0x0c, 0xed, 0xcf, 0xe9,
0xbf, 0xda, 0x11, 0xc2, 0x0a, 0x9c, 0x02, 0x5f, 0xb6, 0xa0, 0xb8,
0xbc, 0xda, 0xbf, 0x80, 0xb4, 0xfb, 0x68, 0xab, 0xc8, 0xa8, 0x07,
0xeb, 0x50, 0x5c, 0x8a, 0x47, 0xcf, 0x61, 0x91, 0x5f};
const uint8_t kP256SignatureUnpaddedSigShort[] = {
0x3d, 0x99, 0x94, 0xa9, 0x80, 0x12, 0x43, 0x27, 0xde, 0x78, 0x9e,
0x61, 0xaf, 0x10, 0xee, 0xd2, 0x22, 0xc6, 0x6e, 0x1c, 0xdf, 0xe7,
0x75, 0x28, 0x84, 0xae, 0xb8, 0xdb, 0x7b, 0xf1, 0x91, 0x86, 0x5b,
0x5a, 0x28, 0x16, 0x15, 0xfe, 0xd9, 0x48, 0x33, 0x95, 0xa8, 0x8f,
0x92, 0xbb, 0xe3, 0x9c, 0xca, 0x04, 0xef, 0x56, 0x48, 0x16, 0x73,
0xa6, 0xb6, 0x6a, 0x38, 0xc9, 0x78, 0xc4};
} // namespace nss_test

View File

@ -239,6 +239,9 @@ TEST(RsaPkcs1Test, Pkcs1MinimumPadding) {
SECItem hash_item = {siBuffer, toUcharPtr(hash.data()),
static_cast<unsigned int>(hash.len())};
SECItem sig_item = {siBuffer, toUcharPtr(sig.data()), sig_len};
/* don't let policy foil us */
NSS_OptionSet(NSS_KEY_SIZE_POLICY_CLEAR_FLAGS,
NSS_KEY_SIZE_POLICY_VERIFY_FLAG);
rv = VFY_VerifyDigestDirect(&hash_item, short_pub.get(), &sig_item,
SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_SHA512,
nullptr);

View File

@ -64,6 +64,22 @@ TEST_F(SoftokenBuiltinsTest, CheckNoDistrustFields) {
EXPECT_EQ(PR_FALSE,
PK11_HasAttributeSet(cert->slot, cert->pkcs11ID,
CKA_NSS_EMAIL_DISTRUST_AFTER, PR_FALSE));
SECStatus rv;
PRBool isDistrusted;
PRTime distrustAfter;
rv = PK11_ReadDistrustAfterAttribute(cert->slot, cert->pkcs11ID,
CKA_NSS_SERVER_DISTRUST_AFTER,
&isDistrusted, &distrustAfter);
EXPECT_EQ(SECSuccess, rv);
EXPECT_EQ(PR_FALSE, isDistrusted);
rv = PK11_ReadDistrustAfterAttribute(cert->slot, cert->pkcs11ID,
CKA_NSS_EMAIL_DISTRUST_AFTER,
&isDistrusted, &distrustAfter);
EXPECT_EQ(SECSuccess, rv);
EXPECT_EQ(PR_FALSE, isDistrusted);
ASSERT_FALSE(cert->distrust);
}
@ -95,6 +111,23 @@ TEST_F(SoftokenBuiltinsTest, CheckOkDistrustFields) {
EXPECT_TRUE(!memcmp(kExpectedDERValueEmail,
cert->distrust->emailDistrustAfter.data,
kDistrustFieldSize));
SECStatus rv;
PRBool isDistrusted;
PRTime distrustAfter;
rv = PK11_ReadDistrustAfterAttribute(cert->slot, cert->pkcs11ID,
CKA_NSS_SERVER_DISTRUST_AFTER,
&isDistrusted, &distrustAfter);
EXPECT_EQ(SECSuccess, rv);
EXPECT_EQ(PR_TRUE, isDistrusted);
EXPECT_EQ(1592352000000000, distrustAfter);
rv = PK11_ReadDistrustAfterAttribute(cert->slot, cert->pkcs11ID,
CKA_NSS_EMAIL_DISTRUST_AFTER,
&isDistrusted, &distrustAfter);
EXPECT_EQ(SECSuccess, rv);
EXPECT_EQ(PR_TRUE, isDistrusted);
EXPECT_EQ(1192352000000000, distrustAfter);
}
TEST_F(SoftokenBuiltinsTest, CheckInvalidDistrustFields) {
@ -119,6 +152,19 @@ TEST_F(SoftokenBuiltinsTest, CheckInvalidDistrustFields) {
PK11_HasAttributeSet(cert->slot, cert->pkcs11ID,
CKA_NSS_EMAIL_DISTRUST_AFTER, PR_FALSE));
ASSERT_FALSE(cert->distrust);
SECStatus rv;
PRBool isDistrusted;
PRTime distrustAfter;
rv = PK11_ReadDistrustAfterAttribute(cert->slot, cert->pkcs11ID,
CKA_NSS_SERVER_DISTRUST_AFTER,
&isDistrusted, &distrustAfter);
EXPECT_EQ(SECFailure, rv);
rv = PK11_ReadDistrustAfterAttribute(cert->slot, cert->pkcs11ID,
CKA_NSS_EMAIL_DISTRUST_AFTER,
&isDistrusted, &distrustAfter);
EXPECT_EQ(SECFailure, rv);
}
} // namespace nss_test

View File

@ -229,13 +229,19 @@ static SECStatus SimpleXorCertCompEncode(const SECItem* input,
}
/* Test decoding function. */
static SECStatus SimpleXorCertCompDecode(const SECItem* input, SECItem* output,
size_t expectedLenDecodedCertificate) {
PORT_Memcpy(output->data, input->data, input->len);
for (size_t i = 0; i < output->len; i++) {
output->data[i] ^= 0x55;
static SECStatus SimpleXorCertCompDecode(const SECItem* input, uint8_t* output,
size_t outputLen,
size_t* receivedOutputLen) {
if (input->len != outputLen) {
return SECFailure;
}
PORT_Memcpy(output, input->data, input->len);
for (size_t i = 0; i < outputLen; i++) {
output[i] ^= 0x55;
}
*receivedOutputLen = outputLen;
return SECSuccess;
}
@ -249,14 +255,20 @@ static SECStatus SimpleXorWithDifferentValueEncode(const SECItem* input,
}
/* Test decoding function. */
static SECStatus SimpleXorWithDifferentValueDecode(
const SECItem* input, SECItem* output,
size_t expectedLenDecodedCertificate) {
PORT_Memcpy(output->data, input->data, input->len);
for (size_t i = 0; i < output->len; i++) {
output->data[i] ^= 0x77;
static SECStatus SimpleXorWithDifferentValueDecode(const SECItem* input,
uint8_t* output,
size_t outputLen,
size_t* receivedOutputLen) {
if (input->len != outputLen) {
return SECFailure;
}
PORT_Memcpy(output, input->data, input->len);
for (size_t i = 0; i < outputLen; i++) {
output[i] ^= 0x77;
}
*receivedOutputLen = outputLen;
return SECSuccess;
}
@ -1235,8 +1247,8 @@ static SECStatus SimpleXorCertCompEncode_always_error(const SECItem* input,
/* Test decoding function. Returns error unconditionally. */
static SECStatus SimpleXorCertCompDecode_always_error(
const SECItem* input, SECItem* output,
size_t expectedLenDecodedCertificate) {
const SECItem* input, uint8_t* output, size_t outputLen,
size_t* receivedOutputLen) {
return SECFailure;
}
@ -1293,6 +1305,48 @@ TEST_F(TlsConnectStreamTls13, CertificateCompression_CertificateCannotDecode) {
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CERTIFICATE);
}
/* Decoding function returning unexpected decoded certificate length. */
static SECStatus WrongUsedLenCertCompDecode(const SECItem* input,
uint8_t* output, size_t outputLen,
size_t* receivedOutputLen) {
if (input->len != outputLen) {
return SECFailure;
}
PORT_Memcpy(output, input->data, input->len);
*receivedOutputLen = outputLen - 1;
return SECSuccess;
}
TEST_F(TlsConnectStreamTls13,
CertificateCompression_WrongDecodedCertificateLength) {
EnsureTlsSetup();
SSLCertificateCompressionAlgorithm t = {0xff01, "test function",
SimpleXorCertCompEncode,
WrongUsedLenCertCompDecode};
EXPECT_EQ(SECSuccess,
SSLExp_SetCertificateCompressionAlgorithm(server_->ssl_fd(), t));
EXPECT_EQ(SECSuccess,
SSLExp_SetCertificateCompressionAlgorithm(client_->ssl_fd(), t));
ExpectAlert(client_, kTlsAlertBadCertificate);
StartConnect();
client_->SetServerKeyBits(server_->server_key_bits());
client_->Handshake();
server_->Handshake();
ASSERT_TRUE_WAIT(client_->state() != TlsAgent::STATE_CONNECTING, 5000);
server_->ExpectReceiveAlert(kTlsAlertCloseNotify);
client_->ExpectSendAlert(kTlsAlertCloseNotify);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CERTIFICATE);
}
/* The test checking the client authentification is successful using certificate
* compression. */
TEST_F(TlsConnectStreamTls13, CertificateCompression_PostAuth) {

View File

@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <limits.h>
#include "prprf.h"
#include "cert.h"
#include "certi.h"
@ -599,6 +600,8 @@ typedef enum {
* Some callers will do quoting when needed, others will not.
* If a caller selects minimalEscapeAndQuote, and the string does not
* need quoting, then this function changes it to minimalEscape.
* Limit source to 16K, which avoids any possibility of overflow.
* Maximum output size would be 3*srclen+2.
*/
static int
cert_RFC1485_GetRequiredLen(const char* src, int srclen, EQMode* pEQMode)
@ -608,6 +611,10 @@ cert_RFC1485_GetRequiredLen(const char* src, int srclen, EQMode* pEQMode)
PRBool needsQuoting = PR_FALSE;
char lastC = 0;
/* avoids needing to check for overflow */
if (srclen > 16384) {
return -1;
}
/* need to make an initial pass to determine if quoting is needed */
for (i = 0; i < srclen; i++) {
char c = src[i];
@ -637,6 +644,7 @@ cert_RFC1485_GetRequiredLen(const char* src, int srclen, EQMode* pEQMode)
reqLen += 2;
if (pEQMode && mode == minimalEscapeAndQuote && !needsQuoting)
*pEQMode = minimalEscape;
/* Maximum output size would be 3*srclen+2 */
return reqLen;
}
@ -648,12 +656,14 @@ escapeAndQuote(char* dst, int dstlen, char* src, int srclen, EQMode* pEQMode)
int i, reqLen = 0;
EQMode mode = pEQMode ? *pEQMode : minimalEscape;
reqLen = cert_RFC1485_GetRequiredLen(src, srclen, &mode);
/* reqLen is max 16384*3 + 2 */
/* space for terminal null */
reqLen = cert_RFC1485_GetRequiredLen(src, srclen, &mode) + 1;
if (reqLen > dstlen) {
if (reqLen < 0 || reqLen+1 > dstlen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
reqLen += 1;
if (mode == minimalEscapeAndQuote)
*dst++ = C_DOUBLE_QUOTE;
@ -981,8 +991,22 @@ AppendAVA(stringBuf* bufp, CERTAVA* ava, CertStrictnessLevel strict)
}
nameLen = strlen(tagName);
valueLen =
(useHex ? avaValue->len : cert_RFC1485_GetRequiredLen((char*)avaValue->data, avaValue->len, &mode));
if (useHex) {
valueLen = avaValue->len;
} else {
int reqLen = cert_RFC1485_GetRequiredLen((char*)avaValue->data, avaValue->len, &mode);
if (reqLen < 0) {
SECITEM_FreeItem(avaValue, PR_TRUE);
return SECFailure;
}
valueLen = reqLen;
}
if (UINT_MAX - nameLen < 2 ||
valueLen > UINT_MAX - nameLen - 2) {
SECITEM_FreeItem(avaValue, PR_TRUE);
return SECFailure;
}
len = nameLen + valueLen + 2; /* Add 2 for '=' and trailing NUL */
maxName = nameLen;
@ -1198,20 +1222,23 @@ avaToString(PLArenaPool* arena, CERTAVA* ava)
if (!avaValue) {
return buf;
}
valueLen =
cert_RFC1485_GetRequiredLen((char*)avaValue->data, avaValue->len, NULL) + 1;
if (arena) {
buf = (char*)PORT_ArenaZAlloc(arena, valueLen);
} else {
buf = (char*)PORT_ZAlloc(valueLen);
}
if (buf) {
SECStatus rv =
escapeAndQuote(buf, valueLen, (char*)avaValue->data, avaValue->len, NULL);
if (rv != SECSuccess) {
if (!arena)
PORT_Free(buf);
buf = NULL;
int reqLen = cert_RFC1485_GetRequiredLen((char*)avaValue->data, avaValue->len, NULL);
/* reqLen is max 16384*3 + 2 */
if (reqLen >= 0) {
valueLen = reqLen + 1;
if (arena) {
buf = (char*)PORT_ArenaZAlloc(arena, valueLen);
} else {
buf = (char*)PORT_ZAlloc(valueLen);
}
if (buf) {
SECStatus rv =
escapeAndQuote(buf, valueLen, (char*)avaValue->data, avaValue->len, NULL);
if (rv != SECSuccess) {
if (!arena)
PORT_Free(buf);
buf = NULL;
}
}
}
SECITEM_FreeItem(avaValue, PR_TRUE);

View File

@ -44,7 +44,7 @@ checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
SECOidTag sigAlg;
SECOidTag curve;
PRUint32 policyFlags = 0;
PRInt32 minLen, len;
PRInt32 minLen, len, optFlags;
sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
@ -109,6 +109,13 @@ checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
return SECFailure;
}
if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
return SECSuccess;
}
if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
return SECSuccess;
}
len = 8 * key->u.rsa.modulus.len;
rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen);
@ -131,6 +138,12 @@ checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
return SECSuccess;
}
if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
return SECSuccess;
}
len = 8 * key->u.dsa.params.prime.len;
@ -162,6 +175,7 @@ CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
SECOidTag sigAlg;
SECOidTag encAlg;
SECOidTag hashAlg;
CK_MECHANISM_TYPE mech;
PRUint32 policyFlags;
if (!pubKey || !sd) {
@ -173,7 +187,7 @@ CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
sigAlg = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
rv = sec_DecodeSigAlg(pubKey, sigAlg,
&sd->signatureAlgorithm.parameters,
&encAlg, &hashAlg);
&encAlg, &hashAlg, &mech, NULL);
if (rv != SECSuccess) {
return SECFailure; /* error is set */
}

View File

@ -39,7 +39,7 @@ pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
PRInt32 parallelFnInvocationCount;
#endif /* PKIX_OBJECT_LEAK_TEST */
static PRBool usePKIXValidationEngine = PR_FALSE;
static PRBool usePKIXValidationEngine = PR_TRUE;
#endif /* NSS_DISABLE_LIBPKIX */
/*

View File

@ -25359,3 +25359,126 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "FIRMAPROFESIONAL CA ROOT-A WEB"
#
# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB,OID.2.5.4.97=VATES-A62634068,O=Firmaprofesional SA,C=ES
# Serial Number:31:97:21:ed:af:89:42:7f:35:41:87:a1:67:56:4c:6d
# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB,OID.2.5.4.97=VATES-A62634068,O=Firmaprofesional SA,C=ES
# Not Valid Before: Wed Apr 06 09:01:36 2022
# Not Valid After : Sun Mar 31 09:01:36 2047
# Fingerprint (SHA-256): BE:F2:56:DA:F2:6E:9C:69:BD:EC:16:02:35:97:98:F3:CA:F7:18:21:A0:3E:01:82:57:C5:3C:65:61:7F:3D:4A
# Fingerprint (SHA1): A8:31:11:74:A6:14:15:0D:CA:77:DD:0E:E4:0C:5D:58:FC:A0:72:A5
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "FIRMAPROFESIONAL CA ROOT-A WEB"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\156\061\013\060\011\006\003\125\004\006\023\002\105\123\061
\034\060\032\006\003\125\004\012\014\023\106\151\162\155\141\160
\162\157\146\145\163\151\157\156\141\154\040\123\101\061\030\060
\026\006\003\125\004\141\014\017\126\101\124\105\123\055\101\066
\062\066\063\064\060\066\070\061\047\060\045\006\003\125\004\003
\014\036\106\111\122\115\101\120\122\117\106\105\123\111\117\116
\101\114\040\103\101\040\122\117\117\124\055\101\040\127\105\102
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\156\061\013\060\011\006\003\125\004\006\023\002\105\123\061
\034\060\032\006\003\125\004\012\014\023\106\151\162\155\141\160
\162\157\146\145\163\151\157\156\141\154\040\123\101\061\030\060
\026\006\003\125\004\141\014\017\126\101\124\105\123\055\101\066
\062\066\063\064\060\066\070\061\047\060\045\006\003\125\004\003
\014\036\106\111\122\115\101\120\122\117\106\105\123\111\117\116
\101\114\040\103\101\040\122\117\117\124\055\101\040\127\105\102
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\020\061\227\041\355\257\211\102\177\065\101\207\241\147\126
\114\155
END
CKA_VALUE MULTILINE_OCTAL
\060\202\002\172\060\202\002\000\240\003\002\001\002\002\020\061
\227\041\355\257\211\102\177\065\101\207\241\147\126\114\155\060
\012\006\010\052\206\110\316\075\004\003\003\060\156\061\013\060
\011\006\003\125\004\006\023\002\105\123\061\034\060\032\006\003
\125\004\012\014\023\106\151\162\155\141\160\162\157\146\145\163
\151\157\156\141\154\040\123\101\061\030\060\026\006\003\125\004
\141\014\017\126\101\124\105\123\055\101\066\062\066\063\064\060
\066\070\061\047\060\045\006\003\125\004\003\014\036\106\111\122
\115\101\120\122\117\106\105\123\111\117\116\101\114\040\103\101
\040\122\117\117\124\055\101\040\127\105\102\060\036\027\015\062
\062\060\064\060\066\060\071\060\061\063\066\132\027\015\064\067
\060\063\063\061\060\071\060\061\063\066\132\060\156\061\013\060
\011\006\003\125\004\006\023\002\105\123\061\034\060\032\006\003
\125\004\012\014\023\106\151\162\155\141\160\162\157\146\145\163
\151\157\156\141\154\040\123\101\061\030\060\026\006\003\125\004
\141\014\017\126\101\124\105\123\055\101\066\062\066\063\064\060
\066\070\061\047\060\045\006\003\125\004\003\014\036\106\111\122
\115\101\120\122\117\106\105\123\111\117\116\101\114\040\103\101
\040\122\117\117\124\055\101\040\127\105\102\060\166\060\020\006
\007\052\206\110\316\075\002\001\006\005\053\201\004\000\042\003
\142\000\004\107\123\352\054\021\244\167\307\052\352\363\326\137
\173\323\004\221\134\372\210\306\042\271\203\020\142\167\204\063
\055\351\003\210\324\340\063\367\355\167\054\112\140\352\344\157
\255\155\264\370\114\212\244\344\037\312\352\117\070\112\056\202
\163\053\307\146\233\012\214\100\234\174\212\366\362\071\140\262
\336\313\354\270\344\157\352\233\135\267\123\220\030\062\125\305
\040\267\224\243\143\060\141\060\017\006\003\125\035\023\001\001
\377\004\005\060\003\001\001\377\060\037\006\003\125\035\043\004
\030\060\026\200\024\223\341\103\143\134\074\235\326\047\363\122
\354\027\262\251\257\054\367\166\370\060\035\006\003\125\035\016
\004\026\004\024\223\341\103\143\134\074\235\326\047\363\122\354
\027\262\251\257\054\367\166\370\060\016\006\003\125\035\017\001
\001\377\004\004\003\002\001\006\060\012\006\010\052\206\110\316
\075\004\003\003\003\150\000\060\145\002\060\035\174\244\173\303
\211\165\063\341\073\251\105\277\106\351\351\241\335\311\042\026
\267\107\021\013\330\232\272\361\310\013\160\120\123\002\221\160
\205\131\251\036\244\346\352\043\061\240\000\002\061\000\375\342
\370\263\257\026\271\036\163\304\226\343\301\060\031\330\176\346
\303\227\336\034\117\270\211\057\063\353\110\017\031\367\207\106
\135\046\220\245\205\305\271\172\224\076\207\250\275\000
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# Trust for "FIRMAPROFESIONAL CA ROOT-A WEB"
# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB,OID.2.5.4.97=VATES-A62634068,O=Firmaprofesional SA,C=ES
# Serial Number:31:97:21:ed:af:89:42:7f:35:41:87:a1:67:56:4c:6d
# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB,OID.2.5.4.97=VATES-A62634068,O=Firmaprofesional SA,C=ES
# Not Valid Before: Wed Apr 06 09:01:36 2022
# Not Valid After : Sun Mar 31 09:01:36 2047
# Fingerprint (SHA-256): BE:F2:56:DA:F2:6E:9C:69:BD:EC:16:02:35:97:98:F3:CA:F7:18:21:A0:3E:01:82:57:C5:3C:65:61:7F:3D:4A
# Fingerprint (SHA1): A8:31:11:74:A6:14:15:0D:CA:77:DD:0E:E4:0C:5D:58:FC:A0:72:A5
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "FIRMAPROFESIONAL CA ROOT-A WEB"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\250\061\021\164\246\024\025\015\312\167\335\016\344\014\135\130
\374\240\162\245
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\202\262\255\105\000\202\260\146\143\370\137\303\147\116\316\243
END
CKA_ISSUER MULTILINE_OCTAL
\060\156\061\013\060\011\006\003\125\004\006\023\002\105\123\061
\034\060\032\006\003\125\004\012\014\023\106\151\162\155\141\160
\162\157\146\145\163\151\157\156\141\154\040\123\101\061\030\060
\026\006\003\125\004\141\014\017\126\101\124\105\123\055\101\066
\062\066\063\064\060\066\070\061\047\060\045\006\003\125\004\003
\014\036\106\111\122\115\101\120\122\117\106\105\123\111\117\116
\101\114\040\103\101\040\122\117\117\124\055\101\040\127\105\102
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\020\061\227\041\355\257\211\102\177\065\101\207\241\147\126
\114\155
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE

View File

@ -12,7 +12,7 @@
#include "secdert.h"
#include "keythi.h"
#include "certt.h"
/*#include "secpkcs5.h" */
#include "secerr.h"
SEC_BEGIN_PROTOS
@ -271,6 +271,10 @@ extern int SECKEY_ECParamsToBasePointOrderLen(const SECItem *params);
*/
SECOidTag SECKEY_GetECCOid(const SECKEYECParams *params);
/* make sure the key length matches the policy for keyType */
SECStatus SECKEY_EnforceKeySize(KeyType keyType, unsigned keyLength,
SECErrorCodes error);
SEC_END_PROTOS
#endif /* _KEYHI_H_ */

View File

@ -12,11 +12,27 @@ SEC_BEGIN_PROTOS
* are good candidates for public functions.. */
KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
/* extract the 'encryption' (could be signing) and hash oids from and
* algorithm, key and parameters (parameters is the parameters field
* of a algorithm ID structure (SECAlgorithmID)*/
/*
* Pulls the hash algorithm, signing algorithm, and key type out of a
* composite algorithm.
*
* key: pointer to the public key. Should be NULL if called for a sign operation.
* sigAlg: the composite algorithm to dissect.
* hashalg: address of a SECOidTag which will be set with the hash algorithm.
* encalg: address of a SECOidTag which will be set with the signing alg.
* mechp: address of a PCKS #11 Mechanism which will be set to the
* combined hash/encrypt mechanism. If set to CKM_INVALID_MECHANISM, the code
* will fall back to external hashing.
* mechparams: address of a SECItem will set to the parameters for the combined
* hash/encrypt mechanism.
*
* Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
* algorithm was not found or was not a signing algorithm.
*/
SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
const SECItem *param, SECOidTag *encalg,
SECOidTag *hashalg, CK_MECHANISM_TYPE *mech,
SECItem *mechparams);
/* just get the 'encryption' oid from the combined signature oid */
SECOidTag sec_GetEncAlgFromSigAlg(SECOidTag sigAlg);
@ -35,11 +51,9 @@ SECStatus sec_DecodeRSAPSSParams(PLArenaPool *arena,
/* convert the encoded RSA-PSS parameters into PKCS #11 mechanism parameters */
SECStatus sec_DecodeRSAPSSParamsToMechanism(PLArenaPool *arena,
const SECItem *params,
CK_RSA_PKCS_PSS_PARAMS *mech);
CK_RSA_PKCS_PSS_PARAMS *mech,
SECOidTag *hashAlg);
/* make sure the key length matches the policy for keyType */
SECStatus seckey_EnforceKeySize(KeyType keyType, unsigned keyLength,
SECErrorCodes error);
SEC_END_PROTOS
#endif /* _KEYHI_H_ */

View File

@ -238,184 +238,6 @@ HASH_GetHashObject(HASH_HashType type)
return &SECHashObjects[type];
}
HASH_HashType
HASH_GetHashTypeByOidTag(SECOidTag hashOid)
{
HASH_HashType ht = HASH_AlgNULL;
switch (hashOid) {
case SEC_OID_MD2:
ht = HASH_AlgMD2;
break;
case SEC_OID_MD5:
ht = HASH_AlgMD5;
break;
case SEC_OID_SHA1:
ht = HASH_AlgSHA1;
break;
case SEC_OID_SHA224:
ht = HASH_AlgSHA224;
break;
case SEC_OID_SHA256:
ht = HASH_AlgSHA256;
break;
case SEC_OID_SHA384:
ht = HASH_AlgSHA384;
break;
case SEC_OID_SHA512:
ht = HASH_AlgSHA512;
break;
case SEC_OID_SHA3_224:
ht = HASH_AlgSHA3_224;
break;
case SEC_OID_SHA3_256:
ht = HASH_AlgSHA3_256;
break;
case SEC_OID_SHA3_384:
ht = HASH_AlgSHA3_384;
break;
case SEC_OID_SHA3_512:
ht = HASH_AlgSHA3_512;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
break;
}
return ht;
}
SECOidTag
HASH_GetHashOidTagByHashType(HASH_HashType type)
{
SECOidTag oid = SEC_OID_UNKNOWN;
switch (type) {
case HASH_AlgMD2:
oid = SEC_OID_MD2;
break;
case HASH_AlgMD5:
oid = SEC_OID_MD5;
break;
case HASH_AlgSHA1:
oid = SEC_OID_SHA1;
break;
case HASH_AlgSHA224:
oid = SEC_OID_SHA224;
break;
case HASH_AlgSHA256:
oid = SEC_OID_SHA256;
break;
case HASH_AlgSHA384:
oid = SEC_OID_SHA384;
break;
case HASH_AlgSHA512:
oid = SEC_OID_SHA512;
break;
case HASH_AlgSHA3_224:
oid = SEC_OID_SHA3_224;
break;
case HASH_AlgSHA3_256:
oid = SEC_OID_SHA3_256;
break;
case HASH_AlgSHA3_384:
oid = SEC_OID_SHA3_384;
break;
case HASH_AlgSHA3_512:
oid = SEC_OID_SHA3_512;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
break;
}
return oid;
}
SECOidTag
HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid)
{
SECOidTag hashOid = SEC_OID_UNKNOWN;
switch (hmacOid) {
/* no oid exists for HMAC_MD2 */
/* NSS does not define a oid for HMAC_MD4 */
case SEC_OID_HMAC_SHA1:
hashOid = SEC_OID_SHA1;
break;
case SEC_OID_HMAC_SHA224:
hashOid = SEC_OID_SHA224;
break;
case SEC_OID_HMAC_SHA256:
hashOid = SEC_OID_SHA256;
break;
case SEC_OID_HMAC_SHA384:
hashOid = SEC_OID_SHA384;
break;
case SEC_OID_HMAC_SHA512:
hashOid = SEC_OID_SHA512;
break;
case SEC_OID_HMAC_SHA3_224:
hashOid = SEC_OID_SHA3_224;
break;
case SEC_OID_HMAC_SHA3_256:
hashOid = SEC_OID_SHA3_256;
break;
case SEC_OID_HMAC_SHA3_384:
hashOid = SEC_OID_SHA3_384;
break;
case SEC_OID_HMAC_SHA3_512:
hashOid = SEC_OID_SHA3_512;
break;
default:
hashOid = SEC_OID_UNKNOWN;
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
break;
}
return hashOid;
}
SECOidTag
HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid)
{
SECOidTag hmacOid = SEC_OID_UNKNOWN;
switch (hashOid) {
/* no oid exists for HMAC_MD2 */
/* NSS does not define a oid for HMAC_MD4 */
case SEC_OID_SHA1:
hmacOid = SEC_OID_HMAC_SHA1;
break;
case SEC_OID_SHA224:
hmacOid = SEC_OID_HMAC_SHA224;
break;
case SEC_OID_SHA256:
hmacOid = SEC_OID_HMAC_SHA256;
break;
case SEC_OID_SHA384:
hmacOid = SEC_OID_HMAC_SHA384;
break;
case SEC_OID_SHA512:
hmacOid = SEC_OID_HMAC_SHA512;
break;
case SEC_OID_SHA3_224:
hmacOid = SEC_OID_HMAC_SHA3_224;
break;
case SEC_OID_SHA3_256:
hmacOid = SEC_OID_HMAC_SHA3_256;
break;
case SEC_OID_SHA3_384:
hmacOid = SEC_OID_HMAC_SHA3_384;
break;
case SEC_OID_SHA3_512:
hmacOid = SEC_OID_HMAC_SHA3_512;
break;
default:
hmacOid = SEC_OID_UNKNOWN;
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
break;
}
return hmacOid;
}
const SECHashObject *
HASH_GetHashObjectByOidTag(SECOidTag hashOid)
{

View File

@ -8,6 +8,8 @@
#include "seccomon.h"
#include "hasht.h"
#include "secoidt.h"
#include "pkcs11t.h"
#include "nsshash.h"
SEC_BEGIN_PROTOS
@ -49,11 +51,7 @@ extern const SECHashObject *HASH_GetHashObject(HASH_HashType type);
extern const SECHashObject *HASH_GetHashObjectByOidTag(SECOidTag hashOid);
extern HASH_HashType HASH_GetHashTypeByOidTag(SECOidTag hashOid);
extern SECOidTag HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid);
extern SECOidTag HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid);
extern SECOidTag HASH_GetHashOidTagByHashType(HASH_HashType type);
extern CK_RSA_PKCS_MGF_TYPE SEC_GetMgfTypeByOidTag(SECOidTag tag);
SEC_END_PROTOS

View File

@ -1345,7 +1345,7 @@ SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
* size.
*/
SECStatus
seckey_EnforceKeySize(KeyType keyType, unsigned keyLength, SECErrorCodes error)
SECKEY_EnforceKeySize(KeyType keyType, unsigned keyLength, SECErrorCodes error)
{
PRInt32 opt = -1;
PRInt32 optVal;
@ -2310,10 +2310,18 @@ sec_GetHashMechanismByOidTag(SECOidTag tag)
}
}
static CK_RSA_PKCS_MGF_TYPE
sec_GetMgfTypeByOidTag(SECOidTag tag)
CK_RSA_PKCS_MGF_TYPE
SEC_GetMgfTypeByOidTag(SECOidTag tag)
{
switch (tag) {
case SEC_OID_SHA3_512:
return CKG_MGF1_SHA3_512;
case SEC_OID_SHA3_384:
return CKG_MGF1_SHA3_384;
case SEC_OID_SHA3_256:
return CKG_MGF1_SHA3_256;
case SEC_OID_SHA3_224:
return CKG_MGF1_SHA3_224;
case SEC_OID_SHA512:
return CKG_MGF1_SHA512;
case SEC_OID_SHA384:
@ -2415,7 +2423,8 @@ sec_DecodeRSAPSSParams(PLArenaPool *arena,
SECStatus
sec_DecodeRSAPSSParamsToMechanism(PLArenaPool *arena,
const SECItem *params,
CK_RSA_PKCS_PSS_PARAMS *mech)
CK_RSA_PKCS_PSS_PARAMS *mech,
SECOidTag *hashAlgp)
{
SECOidTag hashAlg;
SECOidTag maskHashAlg;
@ -2427,13 +2436,14 @@ sec_DecodeRSAPSSParamsToMechanism(PLArenaPool *arena,
if (rv != SECSuccess) {
return SECFailure;
}
*hashAlgp = hashAlg;
mech->hashAlg = sec_GetHashMechanismByOidTag(hashAlg);
if (mech->hashAlg == CKM_INVALID_MECHANISM) {
return SECFailure;
}
mech->mgf = sec_GetMgfTypeByOidTag(maskHashAlg);
mech->mgf = SEC_GetMgfTypeByOidTag(maskHashAlg);
if (mech->mgf == 0) {
return SECFailure;
}

View File

@ -20,10 +20,14 @@
struct SGNContextStr {
SECOidTag signalg;
SECOidTag hashalg;
CK_MECHANISM_TYPE mech;
void *hashcx;
/* if we are using explicitly hashing, this value will be non-null */
const SECHashObject *hashobj;
/* if we are using the combined mechanism, this value will be non-null */
PK11Context *signcx;
SECKEYPrivateKey *key;
SECItem *params;
SECItem mechparams;
};
static SGNContext *
@ -31,6 +35,8 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
{
SGNContext *cx;
SECOidTag hashalg, signalg;
CK_MECHANISM_TYPE mech;
SECItem mechparams;
KeyType keyType;
PRUint32 policyFlags;
PRInt32 optFlags;
@ -44,7 +50,8 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
* it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS.
*/
/* we have a private key, not a public key, so don't pass it in */
rv = sec_DecodeSigAlg(NULL, alg, params, &signalg, &hashalg);
rv = sec_DecodeSigAlg(NULL, alg, params, &signalg, &hashalg, &mech,
&mechparams);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
@ -56,15 +63,15 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
!((key->keyType == dsaKey) && (keyType == fortezzaKey)) &&
!((key->keyType == rsaKey) && (keyType == rsaPssKey))) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
goto loser;
}
if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) {
if (optFlags & NSS_KEY_SIZE_POLICY_SIGN_FLAG) {
rv = seckey_EnforceKeySize(key->keyType,
rv = SECKEY_EnforceKeySize(key->keyType,
SECKEY_PrivateKeyStrengthInBits(key),
SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
if (rv != SECSuccess) {
return NULL;
goto loser;
}
}
}
@ -72,23 +79,28 @@ sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
if ((NSS_GetAlgorithmPolicy(hashalg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return NULL;
goto loser;
}
/* check the policy on the encryption algorithm */
if ((NSS_GetAlgorithmPolicy(signalg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return NULL;
goto loser;
}
cx = (SGNContext *)PORT_ZAlloc(sizeof(SGNContext));
if (cx) {
cx->hashalg = hashalg;
cx->signalg = signalg;
cx->key = key;
cx->params = params;
if (!cx) {
goto loser;
}
cx->hashalg = hashalg;
cx->signalg = signalg;
cx->mech = mech;
cx->key = key;
cx->mechparams = mechparams;
return cx;
loser:
SECITEM_FreeItem(&mechparams, PR_FALSE);
return NULL;
}
SGNContext *
@ -112,19 +124,55 @@ SGN_DestroyContext(SGNContext *cx, PRBool freeit)
(*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
cx->hashcx = NULL;
}
if (cx->signcx != NULL) {
PK11_DestroyContext(cx->signcx, PR_TRUE);
cx->signcx = NULL;
}
SECITEM_FreeItem(&cx->mechparams, PR_FALSE);
if (freeit) {
PORT_ZFree(cx, sizeof(SGNContext));
}
}
}
static PK11Context *
sgn_CreateCombinedContext(SGNContext *cx)
{
/* the particular combination of hash and signature doesn't have a combined
* mechanism, fall back to hand hash & sign */
if (cx->mech == CKM_INVALID_MECHANISM) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
/* the token the private key resides in doesn't support the combined
* mechanism, fall back to hand hash & sign */
if (!PK11_DoesMechanismFlag(cx->key->pkcs11Slot, cx->mech, CKF_SIGN)) {
PORT_SetError(SEC_ERROR_NO_TOKEN);
return NULL;
}
return PK11_CreateContextByPrivKey(cx->mech, CKA_SIGN, cx->key,
&cx->mechparams);
}
SECStatus
SGN_Begin(SGNContext *cx)
{
PK11Context *signcx = NULL;
if (cx->hashcx != NULL) {
(*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
cx->hashcx = NULL;
}
if (cx->signcx != NULL) {
(void)PK11_DestroyContext(cx->signcx, PR_TRUE);
cx->signcx = NULL;
}
/* if we can get a combined context, we'll use that */
signcx = sgn_CreateCombinedContext(cx);
if (signcx != NULL) {
cx->signcx = signcx;
return SECSuccess;
}
cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashalg);
if (!cx->hashobj)
@ -142,8 +190,11 @@ SECStatus
SGN_Update(SGNContext *cx, const unsigned char *input, unsigned int inputLen)
{
if (cx->hashcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
if (cx->signcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
return PK11_DigestOp(cx->signcx, input, inputLen);
}
(*cx->hashobj->update)(cx->hashcx, input, inputLen);
return SECSuccess;
@ -175,12 +226,54 @@ static DERTemplate SGNDigestInfoTemplate[] = {
{ 0 }
};
static SECStatus
sgn_allocateSignatureItem(SECKEYPrivateKey *privKey, SECItem *sigitem)
{
int signatureLen;
signatureLen = PK11_SignatureLen(privKey);
if (signatureLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
return SECFailure;
}
sigitem->len = signatureLen;
sigitem->data = (unsigned char *)PORT_Alloc(signatureLen);
if (sigitem->data == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
return SECSuccess;
}
/* Sometimes the DER signature format for the signature is different than
* The PKCS #11 format for the signature. This code handles the correction
* from PKCS #11 to DER */
static SECStatus
sgn_PKCS11ToX509Sig(SGNContext *cx, SECItem *sigitem)
{
SECStatus rv;
SECItem result = { siBuffer, NULL, 0 };
if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
(cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
/* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
rv = DSAU_EncodeDerSigWithLen(&result, sigitem, sigitem->len);
/* we are done with sigItem. In case of failure, we want to free
* it anyway */
SECITEM_FreeItem(sigitem, PR_FALSE);
if (rv != SECSuccess) {
return rv;
}
*sigitem = result;
}
return SECSuccess;
}
SECStatus
SGN_End(SGNContext *cx, SECItem *result)
{
unsigned char digest[HASH_LENGTH_MAX];
unsigned part1;
int signatureLen;
SECStatus rv;
SECItem digder, sigitem;
PLArenaPool *arena = 0;
@ -191,11 +284,27 @@ SGN_End(SGNContext *cx, SECItem *result)
digder.data = 0;
sigitem.data = 0;
/* Finish up digest function */
if (cx->hashcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
if (cx->signcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we are doing the combined hash/sign function, just finalize
* the signature */
rv = sgn_allocateSignatureItem(privKey, result);
if (rv != SECSuccess) {
return rv;
}
rv = PK11_DigestFinal(cx->signcx, result->data, &result->len,
result->len);
if (rv != SECSuccess) {
SECITEM_ZfreeItem(result, PR_FALSE);
result->data = NULL;
return rv;
}
return sgn_PKCS11ToX509Sig(cx, result);
}
/* Finish up digest function */
(*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));
if (privKey->keyType == rsaKey &&
@ -229,43 +338,13 @@ SGN_End(SGNContext *cx, SECItem *result)
** Encrypt signature after constructing appropriate PKCS#1 signature
** block
*/
signatureLen = PK11_SignatureLen(privKey);
if (signatureLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
rv = SECFailure;
goto loser;
}
sigitem.len = signatureLen;
sigitem.data = (unsigned char *)PORT_Alloc(signatureLen);
if (sigitem.data == NULL) {
rv = SECFailure;
goto loser;
rv = sgn_allocateSignatureItem(privKey, &sigitem);
if (rv != SECSuccess) {
return rv;
}
if (cx->signalg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
CK_RSA_PKCS_PSS_PARAMS mech;
SECItem mechItem = { siBuffer, (unsigned char *)&mech, sizeof(mech) };
PORT_Memset(&mech, 0, sizeof(mech));
if (cx->params && cx->params->data) {
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
rv = SECFailure;
goto loser;
}
rv = sec_DecodeRSAPSSParamsToMechanism(arena, cx->params, &mech);
if (rv != SECSuccess) {
goto loser;
}
} else {
mech.hashAlg = CKM_SHA_1;
mech.mgf = CKG_MGF1_SHA1;
mech.sLen = digder.len;
}
rv = PK11_SignWithMechanism(privKey, CKM_RSA_PKCS_PSS, &mechItem,
rv = PK11_SignWithMechanism(privKey, CKM_RSA_PKCS_PSS, &cx->mechparams,
&sigitem, &digder);
if (rv != SECSuccess) {
goto loser;
@ -276,18 +355,12 @@ SGN_End(SGNContext *cx, SECItem *result)
goto loser;
}
}
if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
(cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
/* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len);
if (rv != SECSuccess)
goto loser;
SECITEM_FreeItem(&sigitem, PR_FALSE);
} else {
result->len = sigitem.len;
result->data = sigitem.data;
rv = sgn_PKCS11ToX509Sig(cx, &sigitem);
*result = sigitem;
if (rv != SECSuccess) {
goto loser;
}
return SECSuccess;
loser:
if (rv != SECSuccess) {
@ -300,6 +373,42 @@ loser:
return rv;
}
static SECStatus
sgn_SingleShot(SGNContext *cx, const unsigned char *input,
unsigned int inputLen, SECItem *result)
{
SECStatus rv;
result->data = 0;
/* if we have the combined mechanism, just do the single shot
* version */
if ((cx->mech != CKM_INVALID_MECHANISM) &&
PK11_DoesMechanismFlag(cx->key->pkcs11Slot, cx->mech, CKF_SIGN)) {
SECItem data = { siBuffer, (unsigned char *)input, inputLen };
rv = sgn_allocateSignatureItem(cx->key, result);
if (rv != SECSuccess) {
return rv;
}
rv = PK11_SignWithMechanism(cx->key, cx->mech, &cx->mechparams,
result, &data);
if (rv != SECSuccess) {
SECITEM_ZfreeItem(result, PR_FALSE);
return rv;
}
return sgn_PKCS11ToX509Sig(cx, result);
}
/* fall back to the stream version */
rv = SGN_Begin(cx);
if (rv != SECSuccess)
return rv;
rv = SGN_Update(cx, input, inputLen);
if (rv != SECSuccess)
return rv;
return SGN_End(cx, result);
}
/************************************************************************/
static SECStatus
@ -314,16 +423,10 @@ sec_SignData(SECItem *res, const unsigned char *buf, int len,
if (sgn == NULL)
return SECFailure;
rv = SGN_Begin(sgn);
rv = sgn_SingleShot(sgn, buf, len, res);
if (rv != SECSuccess)
goto loser;
rv = SGN_Update(sgn, buf, len);
if (rv != SECSuccess)
goto loser;
rv = SGN_End(sgn, res);
loser:
SGN_DestroyContext(sgn, PR_TRUE);
return rv;
@ -483,7 +586,7 @@ SGN_Digest(SECKEYPrivateKey *privKey,
if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) {
if (optFlags & NSS_KEY_SIZE_POLICY_SIGN_FLAG) {
rv = seckey_EnforceKeySize(privKey->keyType,
rv = SECKEY_EnforceKeySize(privKey->keyType,
SECKEY_PrivateKeyStrengthInBits(privKey),
SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
if (rv != SECSuccess) {

View File

@ -17,6 +17,7 @@
#include "secerr.h"
#include "keyi.h"
#include "nss.h"
#include "prenv.h"
/*
** Recover the DigestInfo from an RSA PKCS#1 signature.
@ -139,19 +140,23 @@ struct VFYContextStr {
unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
/* the full RSA signature, only used in RSA-PSS */
unsigned char rsasig[(RSA_MAX_MODULUS_BITS + 7) / 8];
unsigned char gensig[MAX_SIGNATURE_LEN];
} u;
unsigned int signatureLen;
unsigned int pkcs1RSADigestInfoLen;
/* the encoded DigestInfo from a RSA PKCS#1 signature */
unsigned char *pkcs1RSADigestInfo;
void *wincx;
void *hashcx;
const SECHashObject *hashobj;
SECOidTag encAlg; /* enc alg */
PK11Context *vfycx;
SECOidTag encAlg; /* enc alg */
CK_MECHANISM_TYPE mech;
PRBool hasSignature; /* true if the signature was provided in the
* VFY_CreateContext call. If false, the
* signature must be provided with a
* VFY_EndWithSignature call. */
SECItem *params;
SECItem mechparams;
};
static SECStatus
@ -189,6 +194,7 @@ checkedSignatureLen(const SECKEYPublicKey *pubk)
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
return 0;
}
PORT_Assert(maxSigLen <= MAX_SIGNATURE_LEN);
if (sigLen > maxSigLen) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
return 0;
@ -296,30 +302,146 @@ sec_GetEncAlgFromSigAlg(SECOidTag sigAlg)
}
return SEC_OID_UNKNOWN;
}
static CK_MECHANISM_TYPE
sec_RSAPKCS1GetCombinedMech(SECOidTag hashalg)
{
switch (hashalg) {
case SEC_OID_MD5:
return CKM_MD5_RSA_PKCS;
case SEC_OID_MD2:
return CKM_MD2_RSA_PKCS;
case SEC_OID_SHA1:
return CKM_SHA1_RSA_PKCS;
case SEC_OID_SHA224:
return CKM_SHA224_RSA_PKCS;
case SEC_OID_SHA256:
return CKM_SHA256_RSA_PKCS;
case SEC_OID_SHA384:
return CKM_SHA384_RSA_PKCS;
case SEC_OID_SHA512:
return CKM_SHA512_RSA_PKCS;
default:
break;
}
return CKM_INVALID_MECHANISM;
}
static CK_MECHANISM_TYPE
sec_RSAPSSGetCombinedMech(SECOidTag hashalg)
{
switch (hashalg) {
case SEC_OID_SHA1:
return CKM_SHA1_RSA_PKCS_PSS;
case SEC_OID_SHA224:
return CKM_SHA224_RSA_PKCS_PSS;
case SEC_OID_SHA256:
return CKM_SHA256_RSA_PKCS_PSS;
case SEC_OID_SHA384:
return CKM_SHA384_RSA_PKCS_PSS;
case SEC_OID_SHA512:
return CKM_SHA512_RSA_PKCS_PSS;
default:
break;
}
return CKM_INVALID_MECHANISM;
}
static CK_MECHANISM_TYPE
sec_DSAGetCombinedMech(SECOidTag hashalg)
{
switch (hashalg) {
case SEC_OID_SHA1:
return CKM_DSA_SHA1;
case SEC_OID_SHA224:
return CKM_DSA_SHA224;
case SEC_OID_SHA256:
return CKM_DSA_SHA256;
case SEC_OID_SHA384:
return CKM_DSA_SHA384;
case SEC_OID_SHA512:
return CKM_DSA_SHA512;
default:
break;
}
return CKM_INVALID_MECHANISM;
}
static CK_MECHANISM_TYPE
sec_ECDSAGetCombinedMech(SECOidTag hashalg)
{
switch (hashalg) {
case SEC_OID_SHA1:
return CKM_ECDSA_SHA1;
case SEC_OID_SHA224:
return CKM_ECDSA_SHA224;
case SEC_OID_SHA256:
return CKM_ECDSA_SHA256;
case SEC_OID_SHA384:
return CKM_ECDSA_SHA384;
case SEC_OID_SHA512:
return CKM_ECDSA_SHA512;
default:
break;
}
return CKM_INVALID_MECHANISM;
}
static CK_MECHANISM_TYPE
sec_GetCombinedMech(SECOidTag encalg, SECOidTag hashalg)
{
switch (encalg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
return sec_RSAPKCS1GetCombinedMech(hashalg);
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
return sec_RSAPSSGetCombinedMech(hashalg);
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
return sec_ECDSAGetCombinedMech(hashalg);
case SEC_OID_ANSIX9_DSA_SIGNATURE:
return sec_DSAGetCombinedMech(hashalg);
default:
break;
}
return CKM_INVALID_MECHANISM;
}
/*
* Pulls the hash algorithm, signing algorithm, and key type out of a
* composite algorithm.
*
* key: pointer to the public key. Should be NULL if called for a sign operation.
* sigAlg: the composite algorithm to dissect.
* hashalg: address of a SECOidTag which will be set with the hash algorithm.
* encalg: address of a SECOidTag which will be set with the signing alg.
* mechp: address of a PCKS #11 Mechanism which will be set to the
* combined hash/encrypt mechanism. If set to CKM_INVALID_MECHANISM, the code
* will fall back to external hashing.
* mechparams: address of a SECItem will set to the parameters for the combined
* hash/encrypt mechanism.
*
* Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
* algorithm was not found or was not a signing algorithm.
*/
SECStatus
sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg)
const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg,
CK_MECHANISM_TYPE *mechp, SECItem *mechparamsp)
{
unsigned int len;
PLArenaPool *arena;
SECStatus rv;
SECItem oid;
SECOidTag encalg;
char *evp;
PR_ASSERT(hashalg != NULL);
PR_ASSERT(encalgp != NULL);
PR_ASSERT(mechp != NULL);
/* Get the expected combined mechanism from the signature OID
* We'll override it in the table below if necessary */
*mechp = PK11_AlgtagToMechanism(sigAlg);
if (mechparamsp) {
mechparamsp->data = NULL;
mechparamsp->len = 0;
}
switch (sigAlg) {
/* We probably shouldn't be generating MD2 signatures either */
@ -335,24 +457,57 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
*hashalg = SEC_OID_SHA1;
break;
case SEC_OID_PKCS1_RSA_ENCRYPTION:
/* SEC_OID_PKCS1_RSA_ENCRYPTION returns the generic
* CKM_RSA_PKCS mechanism, which isn't a combined mechanism.
* We don't have a hash, so we need to fall back to the old
* code which gets the hashalg by decoding the signature */
*mechp = CKM_INVALID_MECHANISM;
*hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
break;
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
/* SEC_OID_PKCS1_RSA_PSS_SIGNATURE returns the generic
* CKM_RSA_PSS_PKCS mechanism, which isn't a combined mechanism.
* If successful, we'll select the mechanism below, set it to
* invalid here incase we aren't successful */
*mechp = CKM_INVALID_MECHANISM;
CK_RSA_PKCS_PSS_PARAMS *rsapssmechparams = NULL;
CK_RSA_PKCS_PSS_PARAMS space;
/* if we don't have a mechanism parameter to put the data in
* we don't need to return it, just use a stack buffer */
if (mechparamsp == NULL) {
rsapssmechparams = &space;
} else {
rsapssmechparams = PORT_ZNew(CK_RSA_PKCS_PSS_PARAMS);
}
if (rsapssmechparams == NULL) {
return SECFailure;
}
if (param && param->data) {
PORTCheapArenaPool tmpArena;
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
rv = sec_DecodeRSAPSSParams(&tmpArena.arena, param,
hashalg, NULL, NULL);
rv = sec_DecodeRSAPSSParamsToMechanism(&tmpArena.arena, param,
rsapssmechparams, hashalg);
PORT_DestroyCheapArena(&tmpArena);
/* only accept hash algorithms */
if (rv != SECSuccess || HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
/* error set by sec_DecodeRSAPSSParams or HASH_GetHashTypeByOidTag */
if (mechparamsp)
PORT_Free(rsapssmechparams);
return SECFailure;
}
} else {
*hashalg = SEC_OID_SHA1; /* default, SHA-1 */
rsapssmechparams->hashAlg = CKM_SHA_1;
rsapssmechparams->mgf = CKG_MGF1_SHA1;
rsapssmechparams->sLen = SHA1_LENGTH;
}
*mechp = sec_RSAPSSGetCombinedMech(*hashalg);
if (mechparamsp) {
mechparamsp->data = (unsigned char *)rsapssmechparams;
mechparamsp->len = sizeof(*rsapssmechparams);
}
break;
@ -385,6 +540,7 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_KEA_DSS_OLD:
case SEC_OID_MISSI_DSS_OLD:
*mechp = CKM_DSA_SHA1;
*hashalg = SEC_OID_SHA1;
break;
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
@ -406,6 +562,7 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
/* use the largest in this case */
*hashalg = SEC_OID_SHA512;
}
*mechp = sec_ECDSAGetCombinedMech(*hashalg);
break;
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
if (param == NULL) {
@ -429,23 +586,110 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
/* error set by HASH_GetHashTypeByOidTag */
return SECFailure;
}
*mechp = sec_ECDSAGetCombinedMech(*hashalg);
break;
/* we don't implement MD4 hashes */
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
default:
*mechp = CKM_INVALID_MECHANISM;
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
encalg = sec_GetEncAlgFromSigAlg(sigAlg);
if (encalg == SEC_OID_UNKNOWN) {
*mechp = CKM_INVALID_MECHANISM;
SECITEM_FreeItem(mechparamsp, PR_FALSE);
return SECFailure;
}
*encalgp = encalg;
/* for testing, we want to be able to turn off combo signatures to
* 1) make sure the fallback code is working correctly so we know
* we can handle cases where the fallback doesn't work.
* 2) make sure that the combo code is compatible with the non-combo
* versions.
* We know if we are signing or verifying based on the value of 'key'.
* Since key is a public key, then it's set to NULL for signing */
evp = PR_GetEnvSecure("NSS_COMBO_SIGNATURES");
if (evp) {
if (PORT_Strcasecmp(evp, "none") == 0) {
*mechp = CKM_INVALID_MECHANISM;
} else if (key && (PORT_Strcasecmp(evp, "signonly") == 0)) {
*mechp = CKM_INVALID_MECHANISM;
} else if (!key && (PORT_Strcasecmp(evp, "vfyonly") == 0)) {
*mechp = CKM_INVALID_MECHANISM;
}
/* anything else we take as use combo, which is the default */
}
return SECSuccess;
}
SECStatus
vfy_ImportPublicKey(VFYContext *cx)
{
PK11SlotInfo *slot;
CK_OBJECT_HANDLE objID;
if (cx->key->pkcs11Slot &&
PK11_DoesMechanismFlag(cx->key->pkcs11Slot,
cx->mech, CKF_VERIFY)) {
return SECSuccess;
}
slot = PK11_GetBestSlotWithAttributes(cx->mech, CKF_VERIFY, 0, cx->wincx);
if (slot == NULL) {
return SECFailure; /* can't find a slot, fall back to
* normal processing */
}
objID = PK11_ImportPublicKey(slot, cx->key, PR_FALSE);
PK11_FreeSlot(slot);
return objID == CK_INVALID_HANDLE ? SECFailure : SECSuccess;
}
/* Sometimes there are differences between how DER encodes a
* signature and how it's encoded in PKCS #11. This function converts the
* DER form to the PKCS #11 form. it also verify signature length based
* on the key, and verifies that length will fit in our buffer. */
static SECStatus
vfy_SetPKCS11SigFromX509Sig(VFYContext *cx, const SECItem *sig)
{
unsigned int sigLen;
/* skip the legacy RSA PKCS #11 case, it's always handled separately */
if ((cx->key->keyType == rsaKey) && (cx->mech == CKM_INVALID_MECHANISM) &&
(cx->encAlg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE)) {
return SECSuccess;
}
sigLen = checkedSignatureLen(cx->key);
/* Check signature length is within limits */
if (sigLen == 0) {
/* error set by checkedSignatureLen */
return SECFailure;
}
if (sigLen > sizeof(cx->u)) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
/* save the authenticated length */
cx->signatureLen = sigLen;
switch (cx->encAlg) {
case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
/* decodeECorDSASignature will check sigLen == sig->len after padding */
return decodeECorDSASignature(cx->encAlg, sig, cx->u.buffer, sigLen);
default:
break;
}
/* all other cases, no transform needed, just copy the signature */
if (sig->len != sigLen) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
return SECSuccess;
}
/*
* we can verify signatures that come from 2 different sources:
* one in with the signature contains a signature oid, and the other
@ -453,6 +697,17 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
* and a hash oid. The latter is the more basic, so that's what
* our base vfyCreate function takes.
*
* Modern signature algorithms builds the hashing into the algorithm, and
* some tokens (like smart cards), purposefully only export hash & sign
* combo mechanisms (which gives stronger guarrentees on key type usage
* for RSA operations). If mech is set to a PKCS #11 mechanism, we assume
* we can do the combined operations, otherwise we fall back to manually
* hashing then signing.
*
* This function adopts the mechparamsp parameter, so if we fail before
* setting up the context, we need to free any space associated with it
* before we return.
*
* There is one noteworthy corner case, if we are using an RSA key, and the
* signature block is provided, then the hashAlg can be specified as
* SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
@ -460,11 +715,12 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
*/
static VFYContext *
vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx)
SECOidTag encAlg, SECOidTag hashAlg, CK_MECHANISM_TYPE mech,
SECItem *mechparamsp, SECOidTag *hash, PRBool prehash,
void *wincx)
{
VFYContext *cx;
SECStatus rv;
unsigned int sigLen;
KeyType type;
PRUint32 policyFlags;
PRInt32 optFlags;
@ -474,15 +730,17 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
type = seckey_GetKeyType(encAlg);
if ((key->keyType != type) &&
((key->keyType != rsaKey) || (type != rsaPssKey))) {
SECITEM_FreeItem(mechparamsp, PR_FALSE);
PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
return NULL;
}
if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) {
if (optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) {
rv = seckey_EnforceKeySize(key->keyType,
rv = SECKEY_EnforceKeySize(key->keyType,
SECKEY_PublicKeyStrengthInBits(key),
SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
if (rv != SECSuccess) {
SECITEM_FreeItem(mechparamsp, PR_FALSE);
return NULL;
}
}
@ -490,12 +748,16 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
/* check the policy on the encryption algorithm */
if ((NSS_GetAlgorithmPolicy(encAlg, &policyFlags) == SECFailure) ||
!(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
SECITEM_FreeItem(mechparamsp, PR_FALSE);
PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
return NULL;
}
cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext));
if (cx == NULL) {
/* after this point mechparamsp is 'owned' by the context and will be
* freed by Destroy context for any other failures here */
SECITEM_FreeItem(mechparamsp, PR_FALSE);
goto loser;
}
@ -503,50 +765,46 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
cx->hasSignature = (sig != NULL);
cx->encAlg = encAlg;
cx->hashAlg = hashAlg;
cx->mech = mech;
if (mechparamsp) {
cx->mechparams = *mechparamsp;
} else {
/* probably needs to have a call to set the default
* paramseters based on hashAlg and encAlg */
cx->mechparams.data = NULL;
cx->mechparams.len = 0;
}
cx->key = SECKEY_CopyPublicKey(key);
cx->pkcs1RSADigestInfo = NULL;
rv = SECSuccess;
if (mech != CKM_INVALID_MECHANISM) {
rv = vfy_ImportPublicKey(cx);
/* if we can't import the key, then we probably can't
* support the requested combined mechanism, fallback
* to the non-combined method */
if (rv != SECSuccess) {
cx->mech = mech = CKM_INVALID_MECHANISM;
}
}
if (sig) {
rv = SECFailure;
if (type == rsaKey) {
/* sigh, if we are prehashing, we still need to do verifyRecover
* recover for RSA PKCS #1 */
if ((mech == CKM_INVALID_MECHANISM || prehash) && (type == rsaKey)) {
/* in traditional rsa PKCS #1, we use verify recover to get
* the encoded RSADigestInfo. In all other cases we just
* stash the signature encoded in PKCS#11 in our context */
rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
&cx->pkcs1RSADigestInfo,
&cx->pkcs1RSADigestInfoLen,
cx->key,
sig, wincx);
} else {
sigLen = checkedSignatureLen(key);
/* Check signature length is within limits */
if (sigLen == 0) {
/* error set by checkedSignatureLen */
rv = SECFailure;
goto loser;
}
if (sigLen > sizeof(cx->u)) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
rv = SECFailure;
goto loser;
}
switch (type) {
case rsaPssKey:
if (sig->len != sigLen) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
rv = SECFailure;
goto loser;
}
PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
rv = SECSuccess;
break;
case ecKey:
case dsaKey:
/* decodeECorDSASignature will check sigLen == sig->len after padding */
rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
break;
default:
/* Unreachable */
rv = SECFailure;
goto loser;
}
/* at this point hashAlg should be known. Only the RSA case
* enters here with hashAlg unknown, and it's found out
* above */
PORT_Assert(hashAlg != SEC_OID_UNKNOWN);
rv = vfy_SetPKCS11SigFromX509Sig(cx, sig);
}
if (rv != SECSuccess) {
goto loser;
@ -584,11 +842,15 @@ VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
CK_MECHANISM_TYPE mech;
SECItem mechparams;
SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg,
&mech, &mechparams);
if (rv != SECSuccess) {
return NULL;
}
return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
return vfy_CreateContext(key, sig, encAlg, hashAlg, mech,
&mechparams, NULL, PR_FALSE, wincx);
}
VFYContext *
@ -596,28 +858,28 @@ VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
SECOidTag encAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx)
{
return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
return vfy_CreateContext(key, sig, encAlg, hashAlg, mech, NULL,
hash, PR_FALSE, wincx);
}
VFYContext *
VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
{
VFYContext *cx;
SECOidTag encAlg, hashAlg;
CK_MECHANISM_TYPE mech;
SECItem mechparams;
SECStatus rv = sec_DecodeSigAlg(key,
SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
&sigAlgorithm->parameters, &encAlg, &hashAlg);
&sigAlgorithm->parameters, &encAlg, &hashAlg,
&mech, &mechparams);
if (rv != SECSuccess) {
return NULL;
}
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
if (sigAlgorithm->parameters.data) {
cx->params = SECITEM_DupItem(&sigAlgorithm->parameters);
}
return cx;
return vfy_CreateContext(key, sig, encAlg, hashAlg, mech, &mechparams,
hash, PR_FALSE, wincx);
}
void
@ -628,15 +890,17 @@ VFY_DestroyContext(VFYContext *cx, PRBool freeit)
(*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
cx->hashcx = NULL;
}
if (cx->vfycx != NULL) {
(void)PK11_DestroyContext(cx->vfycx, PR_TRUE);
cx->vfycx = NULL;
}
if (cx->key) {
SECKEY_DestroyPublicKey(cx->key);
}
if (cx->pkcs1RSADigestInfo) {
PORT_Free(cx->pkcs1RSADigestInfo);
}
if (cx->params) {
SECITEM_FreeItem(cx->params, PR_TRUE);
}
SECITEM_FreeItem(&cx->mechparams, PR_FALSE);
if (freeit) {
PORT_ZFree(cx, sizeof(VFYContext));
}
@ -650,7 +914,17 @@ VFY_Begin(VFYContext *cx)
(*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
cx->hashcx = NULL;
}
if (cx->vfycx != NULL) {
(void)PK11_DestroyContext(cx->vfycx, PR_TRUE);
cx->vfycx = NULL;
}
if (cx->mech != CKM_INVALID_MECHANISM) {
cx->vfycx = PK11_CreateContextByPubKey(cx->mech, CKA_VERIFY, cx->key,
&cx->mechparams, cx->wincx);
if (!cx->vfycx)
return SECFailure;
return SECSuccess;
}
cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
if (!cx->hashobj)
return SECFailure; /* error code is set */
@ -667,102 +941,87 @@ SECStatus
VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
{
if (cx->hashcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
if (cx->vfycx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
return PK11_DigestOp(cx->vfycx, input, inputLen);
}
(*cx->hashobj->update)(cx->hashcx, input, inputLen);
return SECSuccess;
}
static SECStatus
vfy_SingleShot(VFYContext *cx, const unsigned char *buf, int len)
{
SECStatus rv;
/* if we have the combo mechanism, do a direct verify */
if (cx->mech != CKM_INVALID_MECHANISM) {
SECItem sig = { siBuffer, cx->u.gensig, cx->signatureLen };
SECItem data = { siBuffer, (unsigned char *)buf, len };
return PK11_VerifyWithMechanism(cx->key, cx->mech, &cx->mechparams,
&sig, &data, cx->wincx);
}
rv = VFY_Begin(cx);
if (rv != SECSuccess) {
return rv;
}
rv = VFY_Update(cx, (unsigned char *)buf, len);
if (rv != SECSuccess) {
return rv;
}
return VFY_End(cx);
}
SECStatus
VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
{
unsigned char final[HASH_LENGTH_MAX];
unsigned part;
SECItem hash, rsasig, dsasig; /* dsasig is also used for ECDSA */
SECStatus rv;
if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
/* make sure our signature is set (either previously nor now) */
if (sig) {
rv = vfy_SetPKCS11SigFromX509Sig(cx, sig);
if (rv != SECSuccess) {
return SECFailure;
}
} else if (cx->hasSignature == PR_FALSE) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (cx->hashcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
unsigned int dummy;
if (cx->vfycx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
return PK11_DigestFinal(cx->vfycx, cx->u.gensig, &dummy,
cx->signatureLen);
}
(*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
SECItem gensig = { siBuffer, cx->u.gensig, cx->signatureLen };
SECItem hash = { siBuffer, final, part };
PORT_Assert(part <= sizeof(final));
/* handle the algorithm specific final call */
switch (cx->key->keyType) {
case ecKey:
case dsaKey:
dsasig.len = checkedSignatureLen(cx->key);
if (dsasig.len == 0) {
return SECFailure;
}
if (dsasig.len > sizeof(cx->u)) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
dsasig.data = cx->u.buffer;
if (sig) {
rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
dsasig.len);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
}
hash.data = final;
hash.len = part;
if (PK11_Verify(cx->key, &dsasig, &hash, cx->wincx) != SECSuccess) {
if (PK11_Verify(cx->key, &gensig, &hash, cx->wincx) != SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
break;
case rsaKey:
if (cx->encAlg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
CK_RSA_PKCS_PSS_PARAMS mech;
SECItem mechItem = { siBuffer, (unsigned char *)&mech, sizeof(mech) };
PORTCheapArenaPool tmpArena;
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
rv = sec_DecodeRSAPSSParamsToMechanism(&tmpArena.arena,
cx->params,
&mech);
PORT_DestroyCheapArena(&tmpArena);
if (rv != SECSuccess) {
return SECFailure;
}
rsasig.data = cx->u.buffer;
rsasig.len = checkedSignatureLen(cx->key);
if (rsasig.len == 0) {
/* Error set by checkedSignatureLen */
return SECFailure;
}
if (rsasig.len > sizeof(cx->u)) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
if (sig) {
if (sig->len != rsasig.len) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
PORT_Memcpy(rsasig.data, sig->data, rsasig.len);
}
hash.data = final;
hash.len = part;
if (PK11_VerifyWithMechanism(cx->key, CKM_RSA_PKCS_PSS, &mechItem,
&rsasig, &hash, cx->wincx) != SECSuccess) {
if (PK11_VerifyWithMechanism(cx->key, CKM_RSA_PKCS_PSS,
&cx->mechparams, &gensig, &hash,
cx->wincx) != SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
} else {
SECItem digest;
digest.data = final;
digest.len = part;
if (sig) {
SECOidTag hashid;
PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN);
@ -776,7 +1035,7 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
}
PORT_Assert(cx->hashAlg == hashid);
}
return verifyPKCS1DigestInfo(cx, &digest);
return verifyPKCS1DigestInfo(cx, &hash);
}
break;
default:
@ -799,17 +1058,20 @@ VFY_End(VFYContext *cx)
static SECStatus
vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
void *wincx)
CK_MECHANISM_TYPE mech, SECItem *mechparamsp, void *wincx)
{
SECStatus rv;
VFYContext *cx;
SECItem dsasig; /* also used for ECDSA */
rv = SECFailure;
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, mech, mechparamsp,
NULL, PR_TRUE, wincx);
if (cx != NULL) {
switch (key->keyType) {
case rsaKey:
/* PSS isn't handled here for VerifyDigest. SSL
* calls PK11_Verify directly */
rv = verifyPKCS1DigestInfo(cx, digest);
/* Error (if any) set by verifyPKCS1DigestInfo */
break;
@ -845,7 +1107,9 @@ VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg,
SECOidTag hashAlg, void *wincx)
{
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, mech,
NULL, wincx);
}
SECStatus
@ -853,11 +1117,15 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
SECOidTag algid, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
CK_MECHANISM_TYPE mech;
SECItem mechparams;
SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
&mech, &mechparams);
if (rv != SECSuccess) {
return SECFailure;
}
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg,
mech, &mechparams, wincx);
}
/*
@ -871,42 +1139,43 @@ VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
SECOidTag hashCmp, void *wincx)
{
SECOidTag encAlg, hashAlg;
CK_MECHANISM_TYPE mech;
SECItem mechparams;
SECStatus rv = sec_DecodeSigAlg(key,
SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
&sigAlgorithm->parameters, &encAlg, &hashAlg);
&sigAlgorithm->parameters, &encAlg, &hashAlg,
&mech, &mechparams);
if (rv != SECSuccess) {
return rv;
}
if (hashCmp != SEC_OID_UNKNOWN &&
hashAlg != SEC_OID_UNKNOWN &&
hashCmp != hashAlg) {
if (mechparams.data != NULL) {
PORT_Free(mechparams.data);
}
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg,
mech, &mechparams, wincx);
}
static SECStatus
vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
const SECItem *params, SECOidTag *hash, void *wincx)
CK_MECHANISM_TYPE mech, SECItem *mechparamsp,
SECOidTag *hash, void *wincx)
{
SECStatus rv;
VFYContext *cx;
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, mech, mechparamsp,
hash, PR_FALSE, wincx);
if (cx == NULL)
return SECFailure;
if (params) {
cx->params = SECITEM_DupItem(params);
}
rv = VFY_Begin(cx);
if (rv == SECSuccess) {
rv = VFY_Update(cx, (unsigned char *)buf, len);
if (rv == SECSuccess)
rv = VFY_End(cx);
}
rv = vfy_SingleShot(cx, buf, len);
VFY_DestroyContext(cx, PR_TRUE);
return rv;
@ -918,7 +1187,9 @@ VFY_VerifyDataDirect(const unsigned char *buf, int len,
SECOidTag encAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx)
{
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, hash, wincx);
CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, mech, NULL,
hash, wincx);
}
SECStatus
@ -926,11 +1197,15 @@ VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag algid, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
CK_MECHANISM_TYPE mech;
SECItem mechparams;
SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
&mech, &mechparams);
if (rv != SECSuccess) {
return rv;
}
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, NULL, wincx);
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg,
mech, &mechparams, NULL, wincx);
}
SECStatus
@ -942,11 +1217,14 @@ VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
{
SECOidTag encAlg, hashAlg;
SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
CK_MECHANISM_TYPE mech;
SECItem mechparams;
SECStatus rv = sec_DecodeSigAlg(key, sigAlg,
&sigAlgorithm->parameters, &encAlg, &hashAlg);
&sigAlgorithm->parameters, &encAlg, &hashAlg,
&mech, &mechparams);
if (rv != SECSuccess) {
return rv;
}
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg,
&sigAlgorithm->parameters, hash, wincx);
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, mech,
&mechparams, hash, wincx);
}

View File

@ -209,19 +209,21 @@ create_objects_from_handles(
PRUint32 numH)
{
nssCryptokiObject **objects;
if (numH == PR_UINT32_MAX) {
return NULL; /* avoid overflow in ZNEWARRAY */
}
objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1);
if (objects) {
PRInt32 i;
for (i = 0; i < (PRInt32)numH; i++) {
objects[i] = nssCryptokiObject_Create(tok, session, handles[i]);
if (!objects[i]) {
for (--i; i > 0; --i) {
nssCryptokiObject_Destroy(objects[i]);
}
nss_ZFreeIf(objects);
objects = NULL;
break;
if (!objects) {
return NULL;
}
for (PRUint32 i = 0; i < numH; i++) {
objects[i] = nssCryptokiObject_Create(tok, session, handles[i]);
if (!objects[i]) {
for (; i > 0; --i) {
nssCryptokiObject_Destroy(objects[i - 1]);
}
nss_ZFreeIf(objects);
return NULL;
}
}
return objects;

View File

@ -154,6 +154,10 @@ typedef int __BLAPI_DEPRECATED __attribute__((deprecated));
#define DH_MIN_P_BITS 128
#define DH_MAX_P_BITS 16384
/* max signature for all our supported signatures */
/* currently RSA is the biggest */
#define MAX_SIGNATURE_LEN ((RSA_MAX_MODULUS_BITS + 7) / 8)
/*
* The FIPS 186-1 algorithm for generating primes P and Q allows only 9
* distinct values for the length of P, and only one value for the

File diff suppressed because it is too large Load Diff

View File

@ -32,14 +32,8 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
dstParams->type = srcParams->type;
dstParams->fieldID.size = srcParams->fieldID.size;
dstParams->fieldID.type = srcParams->fieldID.type;
if (srcParams->fieldID.type == ec_field_GFp ||
srcParams->fieldID.type == ec_field_plain) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
&srcParams->fieldID.u.prime));
} else {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
&srcParams->fieldID.u.poly));
}
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
&srcParams->fieldID.u.prime));
dstParams->fieldID.k1 = srcParams->fieldID.k1;
dstParams->fieldID.k2 = srcParams->fieldID.k2;
dstParams->fieldID.k3 = srcParams->fieldID.k3;
@ -79,7 +73,7 @@ gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *par
CHECK_OK(curveParams);
params->fieldID.size = curveParams->size;
params->fieldID.type = field_type;
if (field_type != ec_field_GFp && field_type != ec_field_plain) {
if (field_type != ec_field_plain) {
return SECFailure;
}
params->fieldID.u.prime.len = curveParams->scalarSize;
@ -164,7 +158,7 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
* (the NIST P-384 curve)
*/
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_384R1,
ec_field_GFp, params));
ec_field_plain, params));
break;
case SEC_OID_SECG_EC_SECP521R1:
@ -172,7 +166,7 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
* (the NIST P-521 curve)
*/
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1,
ec_field_GFp, params));
ec_field_plain, params));
break;
case SEC_OID_ED25519_PUBLIC_KEY:

View File

@ -1,163 +0,0 @@
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The ECL exposes routines for constructing and converting curve
parameters for internal use.
HEADER FILES
============
ecl-exp.h - Exports data structures and curve names. For use by code
that does not have access to mp_ints.
ecl-curve.h - Provides hex encodings (in the form of ECCurveParams
structs) of standardizes elliptic curve domain parameters and mappings
from ECCurveName to ECCurveParams. For use by code that does not have
access to mp_ints.
ecl.h - Interface to constructors for curve parameters and group object,
and point multiplication operations. Used by higher level algorithms
(like ECDH and ECDSA) to actually perform elliptic curve cryptography.
ecl-priv.h - Data structures and functions for internal use within the
library.
ecp.h - Internal header file that contains all functions for point
arithmetic over prime fields.
DATA STRUCTURES AND TYPES
=========================
ECCurveName (from ecl-exp.h) - Opaque name for standardized elliptic
curve domain parameters.
ECCurveParams (from ecl-exp.h) - Provides hexadecimal encoding
of elliptic curve domain parameters. Can be generated by a user
and passed to ECGroup_fromHex or can be generated from a name by
EC_GetNamedCurveParams. ecl-curve.h contains ECCurveParams structs for
the standardized curves defined by ECCurveName.
ECGroup (from ecl.h and ecl-priv.h) - Opaque data structure that
represents a group of elliptic curve points for a particular set of
elliptic curve domain parameters. Contains all domain parameters (curve
a and b, field, base point) as well as pointers to the functions that
should be used for point arithmetic and the underlying field GFMethod.
Generated by either ECGroup_fromHex or ECGroup_fromName.
GFMethod (from ecl-priv.h) - Represents a field underlying a set of
elliptic curve domain parameters. Contains the irreducible that defines
the field (either the prime or the binary polynomial) as well as
pointers to the functions that should be used for field arithmetic.
ARITHMETIC FUNCTIONS
====================
Higher-level algorithms (like ECDH and ECDSA) should call ECPoint_mul
or ECPoints_mul (from ecl.h) to do point arithmetic. These functions
will choose which underlying algorithms to use, based on the ECGroup
structure.
Point Multiplication
--------------------
ecl_mult.c provides the ECPoints_mul and ECPoint_mul wrappers.
It also provides two implementations for the pts_mul operation -
ec_pts_mul_basic (which computes kP, lQ, and then adds kP + lQ) and
ec_pts_mul_simul_w2 (which does a simultaneous point multiplication
using a table with window size 2*2).
ec_naf.c provides an implementation of an algorithm to calculate a
non-adjacent form of a scalar, minimizing the number of point
additions that need to be done in a point multiplication.
Point Arithmetic over Prime Fields
----------------------------------
ecp_aff.c provides point arithmetic using affine coordinates.
ecp_jac.c provides point arithmetic using Jacobian projective
coordinates and mixed Jacobian-affine coordinates. (Jacobian projective
coordinates represent a point (x, y) as (X, Y, Z), where x=X/Z^2,
y=Y/Z^3).
ecp_jm.c provides point arithmetic using Modified Jacobian
coordinates and mixed Modified_Jacobian-affine coordinates.
(Modified Jacobian coordinates represent a point (x, y)
as (X, Y, Z, a*Z^4), where x=X/Z^2, y=Y/Z^3, and a is
the linear coefficient in the curve defining equation).
ecp_192.c and ecp_224.c provide optimized field arithmetic.
Field Arithmetic
----------------
ecl_gf.c provides constructors for field objects (GFMethod) with the
functions GFMethod_cons*. It also provides wrappers around the basic
field operations.
Prime Field Arithmetic
----------------------
The mpi library provides the basic prime field arithmetic.
ecp_mont.c provides wrappers around the Montgomery multiplication
functions from the mpi library and adds encoding and decoding functions.
It also provides the function to construct a GFMethod object using
Montgomery multiplication.
ecp_192.c and ecp_224.c provide optimized modular reduction for the
fields defined by nistp192 and nistp224 primes.
ecl_gf.c provides wrappers around the basic field operations.
Field Encoding
--------------
By default, field elements are encoded in their basic form. It is
possible to use an alternative encoding, however. For example, it is
possible to Montgomery representation of prime field elements and
take advantage of the fast modular multiplication that Montgomery
representation provides. The process of converting from basic form to
Montgomery representation is called field encoding, and the opposite
process would be field decoding. All internal point operations assume
that the operands are field encoded as appropriate. By rewiring the
underlying field arithmetic to perform operations on these encoded
values, the same overlying point arithmetic operations can be used
regardless of field representation.
ALGORITHM WIRING
================
The EC library allows point and field arithmetic algorithms to be
substituted ("wired-in") on a fine-grained basis. This allows for
generic algorithms and algorithms that are optimized for a particular
curve, field, or architecture, to coexist and to be automatically
selected at runtime.
Wiring Mechanism
----------------
The ECGroup and GFMethod structure contain pointers to the point and
field arithmetic functions, respectively, that are to be used in
operations.
The selection of algorithms to use is handled in the function
ecgroup_fromNameAndHex in ecl.c.
Default Wiring
--------------
Curves over prime fields by default use montgomery field arithmetic,
point multiplication using 5-bit window non-adjacent-form with
Modified Jacobian coordinates, and 2*2-bit simultaneous point
multiplication using Jacobian coordinates.
(Wiring in function ECGroup_consGFp_mont in ecl.c.)
Curves over prime fields that have optimized modular reduction (i.e.,
secp160r1, nistp192, and nistp224) do not use Montgomery field
arithmetic. Instead, they use basic field arithmetic with their
optimized reduction (as in ecp_192.c and ecp_224.c). They
use the same point multiplication and simultaneous point multiplication
algorithms as other curves over prime fields.

View File

@ -1,68 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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_CHECKOK(mp_sub_d(&k, out[i], &k));
} else {
MP_CHECKOK(mp_add_d(&k, -(out[i]), &k));
}
} else {
out[i] = 0;
}
MP_CHECKOK(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;
}

View File

@ -6,247 +6,7 @@
#define __ecl_priv_h_
#include "ecl.h"
#include "mpi.h"
#include "mplogic.h"
#include "../blapii.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, carry) \
{ \
mp_word w; \
w = ((mp_word)carry) + (a1) + (a2); \
s = ACCUM(w); \
carry = CARRYOUT(w); \
}
#define MP_SUB_BORROW(a1, a2, s, borrow) \
{ \
mp_word w; \
w = ((mp_word)(a1)) - (a2)-borrow; \
s = ACCUM(w); \
borrow = (w >> MP_DIGIT_BIT) & 1; \
}
#else
/* NOTE,
* carry and borrow are both read and written.
* 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, carry) \
{ \
mp_digit tmp, sum; \
tmp = (a1); \
sum = tmp + (a2); \
tmp = (sum < tmp); /* detect overflow */ \
s = sum += carry; \
carry = tmp + (sum < carry); \
}
#define MP_SUB_BORROW(a1, a2, s, borrow) \
{ \
mp_digit tmp; \
tmp = (a1); \
s = tmp - (a2); \
tmp = (s > tmp); /* detect borrow */ \
if (borrow && !s--) \
tmp++; \
borrow = 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);
/* 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;
/* 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);
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);
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);
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);
/* 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 point multiplication */
mp_err ec_group_set_gfp256_32(ECGroup *group, ECCurveName name);
mp_err ec_group_set_secp384r1(ECGroup *group, ECCurveName name);
mp_err ec_group_set_secp521r1(ECGroup *group, ECCurveName name);
SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p);
#endif /* __ecl_priv_h_ */

View File

@ -1,329 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "../stubs.h"
#endif
#include "mpi.h"
#include "mplogic.h"
#include "ecl.h"
#include "ecl-priv.h"
#include "ecp.h"
#include "ecl-curve.h"
#include <stdlib.h>
#include <string.h>
/* Allocate memory for a new ECGroup object. */
ECGroup *
ECGroup_new()
{
mp_err res = MP_OKAY;
ECGroup *group;
group = (ECGroup *)malloc(sizeof(ECGroup));
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));
MP_CHECKOK(mp_init(&group->curveb));
MP_CHECKOK(mp_init(&group->genx));
MP_CHECKOK(mp_init(&group->geny));
MP_CHECKOK(mp_init(&group->order));
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();
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();
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;
}
/* Construct an ECGroup. */
ECGroup *
construct_ecgroup(const ECCurveName name, mp_int irr, mp_int curvea,
mp_int curveb, mp_int genx, mp_int geny, mp_int order,
int cofactor, ECField field, const char *text)
{
int bits;
ECGroup *group = NULL;
mp_err res = MP_OKAY;
/* 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 (field == ECField_GFp) {
switch (name) {
case ECCurve_SECG_PRIME_256R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_gfp256(group, name));
MP_CHECKOK(ec_group_set_gfp256_32(group, name));
break;
case ECCurve_SECG_PRIME_384R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_secp384r1(group, name));
break;
case ECCurve_SECG_PRIME_521R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_gfp521(group, name));
MP_CHECKOK(ec_group_set_secp521r1(group, name));
break;
default:
/* use generic arithmetic */
group =
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
}
} else {
res = MP_UNDEF;
goto CLEANUP;
}
/* set name, if any */
if ((group != NULL) && (text != NULL)) {
group->text = strdup(text);
if (group->text == NULL) {
res = MP_MEM;
}
}
CLEANUP:
if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
}
/* Construct ECGroup from parameters and name, if any. */
ECGroup *
ecgroup_fromName(const ECCurveName name,
const ECCurveBytes *params)
{
mp_int irr, curvea, curveb, genx, geny, order;
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));
MP_CHECKOK(mp_init(&curvea));
MP_CHECKOK(mp_init(&curveb));
MP_CHECKOK(mp_init(&genx));
MP_CHECKOK(mp_init(&geny));
MP_CHECKOK(mp_init(&order));
MP_CHECKOK(mp_read_unsigned_octets(&irr, params->irr, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&curvea, params->curvea, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&curveb, params->curveb, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&genx, params->genx, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&geny, params->geny, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&order, params->order, params->scalarSize));
group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order,
params->cofactor, params->field, params->text);
CLEANUP:
mp_clear(&irr);
mp_clear(&curvea);
mp_clear(&curveb);
mp_clear(&genx);
mp_clear(&geny);
mp_clear(&order);
if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
}
/* Construct ECCurveBytes from an ECCurveName */
const ECCurveBytes *
ec_GetNamedCurveParams(const ECCurveName name)
{
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
(ecCurve_map[name] == NULL)) {
return NULL;
} else {
return ecCurve_map[name];
}
}
/* Construct ECGroup from named parameters. */
ECGroup *
ECGroup_fromName(const ECCurveName name)
{
const ECCurveBytes *params = NULL;
/* This doesn't work with Curve25519 but it's not necessary to. */
PORT_Assert(name != ECCurve25519);
params = ec_GetNamedCurveParams(name);
if (params == NULL) {
return NULL;
}
/* construct actual group */
return ecgroup_fromName(name, params);
}
/* 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)
free(group->text);
if (group->extra_free != NULL)
group->extra_free(group);
free(group);
}

View File

@ -10,39 +10,8 @@
#include "blapi.h"
#include "ecl-exp.h"
#include "mpi.h"
#include "eclt.h"
struct ECGroupStr;
typedef struct ECGroupStr ECGroup;
/* Construct ECGroup from named parameters. */
ECGroup *ECGroup_fromName(const ECCurveName name);
/* Free an allocated ECGroup. */
void ECGroup_free(ECGroup *group);
/* 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);
/* 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);
/* 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);
SECStatus ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P);
SECStatus ec_Curve25519_pt_validate(const SECItem *px);
SECStatus ec_Curve25519_scalar_validate(const SECItem *scalar);
@ -57,8 +26,24 @@ SECStatus ec_secp256r1_sign_digest(ECPrivateKey *key, SECItem *signature,
SECStatus ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
const SECItem *digest);
SECStatus ec_secp384r1_scalar_validate(const SECItem *scalar);
SECStatus ec_secp521r1_pt_mul(SECItem *X, SECItem *k, SECItem *P);
SECStatus ec_secp521r1_pt_validate(const SECItem *px);
SECStatus ec_secp521r1_scalar_validate(const SECItem *scalar);
SECStatus ec_secp521r1_sign_digest(ECPrivateKey *key, SECItem *signature,
const SECItem *digest, const unsigned char *kb,
const unsigned int kblen);
SECStatus ec_secp521r1_verify_digest(ECPublicKey *key, const SECItem *signature,
const SECItem *digest);
SECStatus ec_secp384r1_pt_mul(SECItem *X, SECItem *k, SECItem *P);
SECStatus ec_secp384r1_pt_validate(const SECItem *px);
SECStatus ec_secp384r1_scalar_validate(const SECItem *scalar);
SECStatus ec_secp384r1_sign_digest(ECPrivateKey *key, SECItem *signature,
const SECItem *digest, const unsigned char *kb,
const unsigned int kblen);
SECStatus ec_secp384r1_verify_digest(ECPublicKey *key, const SECItem *signature,
const SECItem *digest);
#endif /* __ecl_h_ */

View File

@ -1,958 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mpi.h"
#include "mp_gf2m.h"
#include "ecl-priv.h"
#include "mpi-priv.h"
#include <stdlib.h>
/* Allocate memory for a new GFMethod object. */
GFMethod *
GFMethod_new()
{
mp_err res = MP_OKAY;
GFMethod *meth;
meth = (GFMethod *)malloc(sizeof(GFMethod));
if (meth == NULL)
return NULL;
meth->constructed = MP_YES;
MP_DIGITS(&meth->irr) = 0;
meth->extra_free = NULL;
MP_CHECKOK(mp_init(&meth->irr));
CLEANUP:
if (res != MP_OKAY) {
GFMethod_free(meth);
return NULL;
}
return meth;
}
/* Construct a generic GFMethod for arithmetic over prime fields with
* irreducible irr. */
GFMethod *
GFMethod_consGFp(const mp_int *irr)
{
mp_err res = MP_OKAY;
GFMethod *meth = NULL;
meth = GFMethod_new();
if (meth == NULL)
return NULL;
MP_CHECKOK(mp_copy(irr, &meth->irr));
meth->irr_arr[0] = mpl_significant_bits(irr);
meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] =
meth->irr_arr[4] = 0;
switch (MP_USED(&meth->irr)) {
/* maybe we need 1 and 2 words here as well?*/
case 3:
meth->field_add = &ec_GFp_add_3;
meth->field_sub = &ec_GFp_sub_3;
break;
case 4:
meth->field_add = &ec_GFp_add_4;
meth->field_sub = &ec_GFp_sub_4;
break;
case 5:
meth->field_add = &ec_GFp_add_5;
meth->field_sub = &ec_GFp_sub_5;
break;
case 6:
meth->field_add = &ec_GFp_add_6;
meth->field_sub = &ec_GFp_sub_6;
break;
default:
meth->field_add = &ec_GFp_add;
meth->field_sub = &ec_GFp_sub;
}
meth->field_neg = &ec_GFp_neg;
meth->field_mod = &ec_GFp_mod;
meth->field_mul = &ec_GFp_mul;
meth->field_sqr = &ec_GFp_sqr;
meth->field_div = &ec_GFp_div;
meth->field_enc = NULL;
meth->field_dec = NULL;
meth->extra1 = NULL;
meth->extra2 = NULL;
meth->extra_free = NULL;
CLEANUP:
if (res != MP_OKAY) {
GFMethod_free(meth);
return NULL;
}
return meth;
}
/* Free the memory allocated (if any) to a GFMethod object. */
void
GFMethod_free(GFMethod *meth)
{
if (meth == NULL)
return;
if (meth->constructed == MP_NO)
return;
mp_clear(&meth->irr);
if (meth->extra_free != NULL)
meth->extra_free(meth);
free(meth);
}
/* Wrapper functions for generic prime field arithmetic. */
/* Add two field elements. Assumes that 0 <= a, b < meth->irr */
mp_err
ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
const GFMethod *meth)
{
/* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */
mp_err res;
if ((res = mp_add(a, b, r)) != MP_OKAY) {
return res;
}
if (mp_cmp(r, &meth->irr) >= 0) {
return mp_sub(r, &meth->irr, r);
}
return res;
}
/* Negates a field element. Assumes that 0 <= a < meth->irr */
mp_err
ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth)
{
/* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */
if (mp_cmp_z(a) == 0) {
mp_zero(r);
return MP_OKAY;
}
return mp_sub(&meth->irr, a, r);
}
/* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */
mp_err
ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
const GFMethod *meth)
{
mp_err res = MP_OKAY;
/* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */
res = mp_sub(a, b, r);
if (res == MP_RANGE) {
MP_CHECKOK(mp_sub(b, a, r));
if (mp_cmp_z(r) < 0) {
MP_CHECKOK(mp_add(r, &meth->irr, r));
}
MP_CHECKOK(ec_GFp_neg(r, r, meth));
}
if (mp_cmp_z(r) < 0) {
MP_CHECKOK(mp_add(r, &meth->irr, r));
}
CLEANUP:
return res;
}
/*
* Inline adds for small curve lengths.
*/
/* 3 words */
mp_err
ec_GFp_add_3(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
carry = 0;
MP_ADD_CARRY(a0, r0, r0, carry);
MP_ADD_CARRY(a1, r1, r1, carry);
MP_ADD_CARRY(a2, r2, r2, 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
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;
/* Do quick 'subract' if we've gone over
* (add the 2's complement of the curve field) */
a2 = MP_DIGIT(&meth->irr, 2);
if (carry || r2 > a2 ||
((r2 == a2) && mp_cmp(r, &meth->irr) != MP_LT)) {
a1 = MP_DIGIT(&meth->irr, 1);
a0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
carry = 0;
MP_SUB_BORROW(r0, a0, r0, carry);
MP_SUB_BORROW(r1, a1, r1, carry);
MP_SUB_BORROW(r2, a2, r2, carry);
#else
__asm__(
"subq %3,%0 \n\t"
"sbbq %4,%1 \n\t"
"sbbq %5,%2 \n\t"
: "=r"(r0), "=r"(r1), "=r"(r2)
: "r"(a0), "r"(a1), "r"(a2),
"0"(r0), "1"(r1), "2"(r2)
: "%cc");
#endif
MP_DIGIT(r, 2) = r2;
MP_DIGIT(r, 1) = r1;
MP_DIGIT(r, 0) = r0;
}
s_mp_clamp(r);
CLEANUP:
return res;
}
/* 4 words */
mp_err
ec_GFp_add_4(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, a3 = 0;
mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
mp_digit carry;
switch (MP_USED(a)) {
case 4:
a3 = MP_DIGIT(a, 3);
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 4:
r3 = MP_DIGIT(b, 3);
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
carry = 0;
MP_ADD_CARRY(a0, r0, r0, carry);
MP_ADD_CARRY(a1, r1, r1, carry);
MP_ADD_CARRY(a2, r2, r2, carry);
MP_ADD_CARRY(a3, r3, r3, carry);
#else
__asm__(
"xorq %4,%4 \n\t"
"addq %5,%0 \n\t"
"adcq %6,%1 \n\t"
"adcq %7,%2 \n\t"
"adcq %8,%3 \n\t"
"adcq $0,%4 \n\t"
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry)
: "r"(a0), "r"(a1), "r"(a2), "r"(a3),
"0"(r0), "1"(r1), "2"(r2), "3"(r3)
: "%cc");
#endif
MP_CHECKOK(s_mp_pad(r, 4));
MP_DIGIT(r, 3) = r3;
MP_DIGIT(r, 2) = r2;
MP_DIGIT(r, 1) = r1;
MP_DIGIT(r, 0) = r0;
MP_SIGN(r) = MP_ZPOS;
MP_USED(r) = 4;
/* Do quick 'subract' if we've gone over
* (add the 2's complement of the curve field) */
a3 = MP_DIGIT(&meth->irr, 3);
if (carry || r3 > a3 ||
((r3 == a3) && mp_cmp(r, &meth->irr) != MP_LT)) {
a2 = MP_DIGIT(&meth->irr, 2);
a1 = MP_DIGIT(&meth->irr, 1);
a0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
carry = 0;
MP_SUB_BORROW(r0, a0, r0, carry);
MP_SUB_BORROW(r1, a1, r1, carry);
MP_SUB_BORROW(r2, a2, r2, carry);
MP_SUB_BORROW(r3, a3, r3, carry);
#else
__asm__(
"subq %4,%0 \n\t"
"sbbq %5,%1 \n\t"
"sbbq %6,%2 \n\t"
"sbbq %7,%3 \n\t"
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
: "r"(a0), "r"(a1), "r"(a2), "r"(a3),
"0"(r0), "1"(r1), "2"(r2), "3"(r3)
: "%cc");
#endif
MP_DIGIT(r, 3) = r3;
MP_DIGIT(r, 2) = r2;
MP_DIGIT(r, 1) = r1;
MP_DIGIT(r, 0) = r0;
}
s_mp_clamp(r);
CLEANUP:
return res;
}
/* 5 words */
mp_err
ec_GFp_add_5(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, a3 = 0, a4 = 0;
mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
mp_digit carry;
switch (MP_USED(a)) {
case 5:
a4 = MP_DIGIT(a, 4);
case 4:
a3 = MP_DIGIT(a, 3);
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 5:
r4 = MP_DIGIT(b, 4);
case 4:
r3 = MP_DIGIT(b, 3);
case 3:
r2 = MP_DIGIT(b, 2);
case 2:
r1 = MP_DIGIT(b, 1);
case 1:
r0 = MP_DIGIT(b, 0);
}
carry = 0;
MP_ADD_CARRY(a0, r0, r0, carry);
MP_ADD_CARRY(a1, r1, r1, carry);
MP_ADD_CARRY(a2, r2, r2, carry);
MP_ADD_CARRY(a3, r3, r3, carry);
MP_ADD_CARRY(a4, r4, r4, carry);
MP_CHECKOK(s_mp_pad(r, 5));
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;
MP_SIGN(r) = MP_ZPOS;
MP_USED(r) = 5;
/* Do quick 'subract' if we've gone over
* (add the 2's complement of the curve field) */
a4 = MP_DIGIT(&meth->irr, 4);
if (carry || r4 > a4 ||
((r4 == a4) && mp_cmp(r, &meth->irr) != MP_LT)) {
a3 = MP_DIGIT(&meth->irr, 3);
a2 = MP_DIGIT(&meth->irr, 2);
a1 = MP_DIGIT(&meth->irr, 1);
a0 = MP_DIGIT(&meth->irr, 0);
carry = 0;
MP_SUB_BORROW(r0, a0, r0, carry);
MP_SUB_BORROW(r1, a1, r1, carry);
MP_SUB_BORROW(r2, a2, r2, carry);
MP_SUB_BORROW(r3, a3, r3, carry);
MP_SUB_BORROW(r4, a4, r4, carry);
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;
}
s_mp_clamp(r);
CLEANUP:
return res;
}
/* 6 words */
mp_err
ec_GFp_add_6(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, a3 = 0, a4 = 0, a5 = 0;
mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
mp_digit carry;
switch (MP_USED(a)) {
case 6:
a5 = MP_DIGIT(a, 5);
case 5:
a4 = MP_DIGIT(a, 4);
case 4:
a3 = MP_DIGIT(a, 3);
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 6:
r5 = MP_DIGIT(b, 5);
case 5:
r4 = MP_DIGIT(b, 4);
case 4:
r3 = MP_DIGIT(b, 3);
case 3:
r2 = MP_DIGIT(b, 2);
case 2:
r1 = MP_DIGIT(b, 1);
case 1:
r0 = MP_DIGIT(b, 0);
}
carry = 0;
MP_ADD_CARRY(a0, r0, r0, carry);
MP_ADD_CARRY(a1, r1, r1, carry);
MP_ADD_CARRY(a2, r2, r2, carry);
MP_ADD_CARRY(a3, r3, r3, carry);
MP_ADD_CARRY(a4, r4, r4, carry);
MP_ADD_CARRY(a5, r5, r5, carry);
MP_CHECKOK(s_mp_pad(r, 6));
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;
MP_SIGN(r) = MP_ZPOS;
MP_USED(r) = 6;
/* Do quick 'subract' if we've gone over
* (add the 2's complement of the curve field) */
a5 = MP_DIGIT(&meth->irr, 5);
if (carry || r5 > a5 ||
((r5 == a5) && mp_cmp(r, &meth->irr) != MP_LT)) {
a4 = MP_DIGIT(&meth->irr, 4);
a3 = MP_DIGIT(&meth->irr, 3);
a2 = MP_DIGIT(&meth->irr, 2);
a1 = MP_DIGIT(&meth->irr, 1);
a0 = MP_DIGIT(&meth->irr, 0);
carry = 0;
MP_SUB_BORROW(r0, a0, r0, carry);
MP_SUB_BORROW(r1, a1, r1, carry);
MP_SUB_BORROW(r2, a2, r2, carry);
MP_SUB_BORROW(r3, a3, r3, carry);
MP_SUB_BORROW(r4, a4, r4, carry);
MP_SUB_BORROW(r5, a5, r5, carry);
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;
}
s_mp_clamp(r);
CLEANUP:
return res;
}
/*
* The following subraction functions do in-line subractions based
* on our curve size.
*
* ... 3 words
*/
mp_err
ec_GFp_sub_3(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
borrow = 0;
MP_SUB_BORROW(r0, b0, r0, borrow);
MP_SUB_BORROW(r1, b1, r1, borrow);
MP_SUB_BORROW(r2, b2, r2, 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) {
b2 = MP_DIGIT(&meth->irr, 2);
b1 = MP_DIGIT(&meth->irr, 1);
b0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
borrow = 0;
MP_ADD_CARRY(b0, r0, r0, borrow);
MP_ADD_CARRY(b1, r1, r1, borrow);
MP_ADD_CARRY(b2, r2, r2, borrow);
#else
__asm__(
"addq %3,%0 \n\t"
"adcq %4,%1 \n\t"
"adcq %5,%2 \n\t"
: "=r"(r0), "=r"(r1), "=r"(r2)
: "r"(b0), "r"(b1), "r"(b2),
"0"(r0), "1"(r1), "2"(r2)
: "%cc");
#endif
}
#ifdef MPI_AMD64_ADD
/* compiler fakeout? */
if ((r2 == b0) && (r1 == b0) && (r0 == b0)) {
MP_CHECKOK(s_mp_pad(r, 4));
}
#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;
}
/* 4 words */
mp_err
ec_GFp_sub_4(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, b3 = 0;
mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
mp_digit borrow;
switch (MP_USED(a)) {
case 4:
r3 = MP_DIGIT(a, 3);
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 4:
b3 = MP_DIGIT(b, 3);
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
borrow = 0;
MP_SUB_BORROW(r0, b0, r0, borrow);
MP_SUB_BORROW(r1, b1, r1, borrow);
MP_SUB_BORROW(r2, b2, r2, borrow);
MP_SUB_BORROW(r3, b3, r3, borrow);
#else
__asm__(
"xorq %4,%4 \n\t"
"subq %5,%0 \n\t"
"sbbq %6,%1 \n\t"
"sbbq %7,%2 \n\t"
"sbbq %8,%3 \n\t"
"adcq $0,%4 \n\t"
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(borrow)
: "r"(b0), "r"(b1), "r"(b2), "r"(b3),
"0"(r0), "1"(r1), "2"(r2), "3"(r3)
: "%cc");
#endif
/* Do quick 'add' if we've gone under 0
* (subtract the 2's complement of the curve field) */
if (borrow) {
b3 = MP_DIGIT(&meth->irr, 3);
b2 = MP_DIGIT(&meth->irr, 2);
b1 = MP_DIGIT(&meth->irr, 1);
b0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
borrow = 0;
MP_ADD_CARRY(b0, r0, r0, borrow);
MP_ADD_CARRY(b1, r1, r1, borrow);
MP_ADD_CARRY(b2, r2, r2, borrow);
MP_ADD_CARRY(b3, r3, r3, borrow);
#else
__asm__(
"addq %4,%0 \n\t"
"adcq %5,%1 \n\t"
"adcq %6,%2 \n\t"
"adcq %7,%3 \n\t"
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
: "r"(b0), "r"(b1), "r"(b2), "r"(b3),
"0"(r0), "1"(r1), "2"(r2), "3"(r3)
: "%cc");
#endif
}
#ifdef MPI_AMD64_ADD
/* compiler fakeout? */
if ((r3 == b0) && (r1 == b0) && (r0 == b0)) {
MP_CHECKOK(s_mp_pad(r, 4));
}
#endif
MP_CHECKOK(s_mp_pad(r, 4));
MP_DIGIT(r, 3) = r3;
MP_DIGIT(r, 2) = r2;
MP_DIGIT(r, 1) = r1;
MP_DIGIT(r, 0) = r0;
MP_SIGN(r) = MP_ZPOS;
MP_USED(r) = 4;
s_mp_clamp(r);
CLEANUP:
return res;
}
/* 5 words */
mp_err
ec_GFp_sub_5(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, b3 = 0, b4 = 0;
mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
mp_digit borrow;
switch (MP_USED(a)) {
case 5:
r4 = MP_DIGIT(a, 4);
case 4:
r3 = MP_DIGIT(a, 3);
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 5:
b4 = MP_DIGIT(b, 4);
case 4:
b3 = MP_DIGIT(b, 3);
case 3:
b2 = MP_DIGIT(b, 2);
case 2:
b1 = MP_DIGIT(b, 1);
case 1:
b0 = MP_DIGIT(b, 0);
}
borrow = 0;
MP_SUB_BORROW(r0, b0, r0, borrow);
MP_SUB_BORROW(r1, b1, r1, borrow);
MP_SUB_BORROW(r2, b2, r2, borrow);
MP_SUB_BORROW(r3, b3, r3, borrow);
MP_SUB_BORROW(r4, b4, r4, borrow);
/* Do quick 'add' if we've gone under 0
* (subtract the 2's complement of the curve field) */
if (borrow) {
b4 = MP_DIGIT(&meth->irr, 4);
b3 = MP_DIGIT(&meth->irr, 3);
b2 = MP_DIGIT(&meth->irr, 2);
b1 = MP_DIGIT(&meth->irr, 1);
b0 = MP_DIGIT(&meth->irr, 0);
borrow = 0;
MP_ADD_CARRY(b0, r0, r0, borrow);
MP_ADD_CARRY(b1, r1, r1, borrow);
MP_ADD_CARRY(b2, r2, r2, borrow);
MP_ADD_CARRY(b3, r3, r3, borrow);
MP_ADD_CARRY(b4, r4, r4, borrow);
}
MP_CHECKOK(s_mp_pad(r, 5));
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;
MP_SIGN(r) = MP_ZPOS;
MP_USED(r) = 5;
s_mp_clamp(r);
CLEANUP:
return res;
}
/* 6 words */
mp_err
ec_GFp_sub_6(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, b3 = 0, b4 = 0, b5 = 0;
mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
mp_digit borrow;
switch (MP_USED(a)) {
case 6:
r5 = MP_DIGIT(a, 5);
case 5:
r4 = MP_DIGIT(a, 4);
case 4:
r3 = MP_DIGIT(a, 3);
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 6:
b5 = MP_DIGIT(b, 5);
case 5:
b4 = MP_DIGIT(b, 4);
case 4:
b3 = MP_DIGIT(b, 3);
case 3:
b2 = MP_DIGIT(b, 2);
case 2:
b1 = MP_DIGIT(b, 1);
case 1:
b0 = MP_DIGIT(b, 0);
}
borrow = 0;
MP_SUB_BORROW(r0, b0, r0, borrow);
MP_SUB_BORROW(r1, b1, r1, borrow);
MP_SUB_BORROW(r2, b2, r2, borrow);
MP_SUB_BORROW(r3, b3, r3, borrow);
MP_SUB_BORROW(r4, b4, r4, borrow);
MP_SUB_BORROW(r5, b5, r5, borrow);
/* Do quick 'add' if we've gone under 0
* (subtract the 2's complement of the curve field) */
if (borrow) {
b5 = MP_DIGIT(&meth->irr, 5);
b4 = MP_DIGIT(&meth->irr, 4);
b3 = MP_DIGIT(&meth->irr, 3);
b2 = MP_DIGIT(&meth->irr, 2);
b1 = MP_DIGIT(&meth->irr, 1);
b0 = MP_DIGIT(&meth->irr, 0);
borrow = 0;
MP_ADD_CARRY(b0, r0, r0, borrow);
MP_ADD_CARRY(b1, r1, r1, borrow);
MP_ADD_CARRY(b2, r2, r2, borrow);
MP_ADD_CARRY(b3, r3, r3, borrow);
MP_ADD_CARRY(b4, r4, r4, borrow);
MP_ADD_CARRY(b5, r5, r5, borrow);
}
MP_CHECKOK(s_mp_pad(r, 6));
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;
MP_SIGN(r) = MP_ZPOS;
MP_USED(r) = 6;
s_mp_clamp(r);
CLEANUP:
return res;
}
/* Reduces an integer to a field element. */
mp_err
ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
{
return mp_mod(a, &meth->irr, r);
}
/* Multiplies two field elements. */
mp_err
ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
const GFMethod *meth)
{
return mp_mulmod(a, b, &meth->irr, r);
}
/* Squares a field element. */
mp_err
ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
{
return mp_sqrmod(a, &meth->irr, r);
}
/* Divides two field elements. If a is NULL, then returns the inverse of
* b. */
mp_err
ec_GFp_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));
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
MP_CHECKOK(mp_mulmod(a, &t, &meth->irr, r));
CLEANUP:
mp_clear(&t);
return res;
}
}
/* Wrapper functions for generic binary polynomial field arithmetic. */
/* Adds two field elements. */
mp_err
ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
const GFMethod *meth)
{
return mp_badd(a, b, r);
}
/* Negates a field element. Note that for binary polynomial fields, the
* negation of a field element is the field element itself. */
mp_err
ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth)
{
if (a == r) {
return MP_OKAY;
} else {
return mp_copy(a, r);
}
}
/* Reduces a binary polynomial to a field element. */
mp_err
ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
{
return mp_bmod(a, meth->irr_arr, r);
}
/* Multiplies two field elements. */
mp_err
ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
const GFMethod *meth)
{
return mp_bmulmod(a, b, meth->irr_arr, r);
}
/* Squares a field element. */
mp_err
ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
{
return mp_bsqrmod(a, meth->irr_arr, r);
}
/* Divides two field elements. If a is NULL, then returns the inverse of
* b. */
mp_err
ec_GF2m_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) {
/* The GF(2^m) portion of MPI doesn't support invmod, so we
* compute 1/b. */
MP_CHECKOK(mp_init(&t));
MP_CHECKOK(mp_set_int(&t, 1));
MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r));
CLEANUP:
mp_clear(&t);
return res;
} else {
return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r);
}
}

View File

@ -1,305 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mpi.h"
#include "mplogic.h"
#include "ecl.h"
#include "ecl-priv.h"
#include <stdlib.h>
/* 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)
{
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));
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 {
MP_CHECKOK(group->point_mul(&kt, &group->genx, &group->geny, rx, ry,
group));
}
} else {
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));
} else {
MP_CHECKOK(group->point_mul(&kt, px, py, 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:
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)
{
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);
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
}
MP_DIGITS(&sx) = 0;
MP_DIGITS(&sy) = 0;
MP_CHECKOK(mp_init(&sx));
MP_CHECKOK(mp_init(&sy));
MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy));
MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry));
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)
{
mp_err res = MP_OKAY;
mp_int precomp[4][4][2];
const mp_int *a, *b;
unsigned 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);
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
}
/* 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));
MP_CHECKOK(mp_init_size(&precomp[i][j][1],
ECL_MAX_FIELD_SIZE_DIGITS));
}
}
/* 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; i-- > 0;) {
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)
{
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));
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));
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);
} else {
res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
}
CLEANUP:
mp_clear(&k1t);
mp_clear(&k2t);
return res;
}

View File

@ -1,106 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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);
/* 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);
#endif /* __ecp_h_ */

View File

@ -9,11 +9,6 @@
#endif
#include "ecl-priv.h"
#include "ecp.h"
#include "mpi.h"
#include "mplogic.h"
#include "mpi-priv.h"
#include "secmpi.h"
#include "secitem.h"
#include "secerr.h"
#include "secport.h"

View File

@ -1,401 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecp.h"
#include "mpi.h"
#include "mplogic.h"
#include "mpi-priv.h"
/* 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. */
static 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 */
carry = 0;
MP_ADD_CARRY(r3, a11, r3, carry);
MP_ADD_CARRY(r4, a12, r4, carry);
MP_ADD_CARRY(r5, a13, r5, carry);
MP_ADD_CARRY(r6, a14, r6, carry);
MP_ADD_CARRY(r7, a15, r7, carry);
r8 = carry;
carry = 0;
MP_ADD_CARRY(r3, a11, r3, carry);
MP_ADD_CARRY(r4, a12, r4, carry);
MP_ADD_CARRY(r5, a13, r5, carry);
MP_ADD_CARRY(r6, a14, r6, carry);
MP_ADD_CARRY(r7, a15, r7, carry);
r8 += carry;
carry = 0;
/* sum 2 */
MP_ADD_CARRY(r3, a12, r3, carry);
MP_ADD_CARRY(r4, a13, r4, carry);
MP_ADD_CARRY(r5, a14, r5, carry);
MP_ADD_CARRY(r6, a15, r6, carry);
MP_ADD_CARRY(r7, 0, r7, carry);
r8 += carry;
carry = 0;
/* combine last bottom of sum 3 with second sum 2 */
MP_ADD_CARRY(r0, a8, r0, carry);
MP_ADD_CARRY(r1, a9, r1, carry);
MP_ADD_CARRY(r2, a10, r2, carry);
MP_ADD_CARRY(r3, a12, r3, carry);
MP_ADD_CARRY(r4, a13, r4, carry);
MP_ADD_CARRY(r5, a14, r5, carry);
MP_ADD_CARRY(r6, a15, r6, carry);
MP_ADD_CARRY(r7, a15, r7, carry); /* from sum 3 */
r8 += carry;
carry = 0;
/* sum 3 (rest of it)*/
MP_ADD_CARRY(r6, a14, r6, carry);
MP_ADD_CARRY(r7, 0, r7, carry);
r8 += carry;
carry = 0;
/* sum 4 (rest of it)*/
MP_ADD_CARRY(r0, a9, r0, carry);
MP_ADD_CARRY(r1, a10, r1, carry);
MP_ADD_CARRY(r2, a11, r2, carry);
MP_ADD_CARRY(r3, a13, r3, carry);
MP_ADD_CARRY(r4, a14, r4, carry);
MP_ADD_CARRY(r5, a15, r5, carry);
MP_ADD_CARRY(r6, a13, r6, carry);
MP_ADD_CARRY(r7, a8, r7, carry);
r8 += carry;
carry = 0;
/* diff 5 */
MP_SUB_BORROW(r0, a11, r0, carry);
MP_SUB_BORROW(r1, a12, r1, carry);
MP_SUB_BORROW(r2, a13, r2, carry);
MP_SUB_BORROW(r3, 0, r3, carry);
MP_SUB_BORROW(r4, 0, r4, carry);
MP_SUB_BORROW(r5, 0, r5, carry);
MP_SUB_BORROW(r6, a8, r6, carry);
MP_SUB_BORROW(r7, a10, r7, carry);
r8 -= carry;
carry = 0;
/* diff 6 */
MP_SUB_BORROW(r0, a12, r0, carry);
MP_SUB_BORROW(r1, a13, r1, carry);
MP_SUB_BORROW(r2, a14, r2, carry);
MP_SUB_BORROW(r3, a15, r3, carry);
MP_SUB_BORROW(r4, 0, r4, carry);
MP_SUB_BORROW(r5, 0, r5, carry);
MP_SUB_BORROW(r6, a9, r6, carry);
MP_SUB_BORROW(r7, a11, r7, carry);
r8 -= carry;
carry = 0;
/* diff 7 */
MP_SUB_BORROW(r0, a13, r0, carry);
MP_SUB_BORROW(r1, a14, r1, carry);
MP_SUB_BORROW(r2, a15, r2, carry);
MP_SUB_BORROW(r3, a8, r3, carry);
MP_SUB_BORROW(r4, a9, r4, carry);
MP_SUB_BORROW(r5, a10, r5, carry);
MP_SUB_BORROW(r6, 0, r6, carry);
MP_SUB_BORROW(r7, a12, r7, carry);
r8 -= carry;
carry = 0;
/* diff 8 */
MP_SUB_BORROW(r0, a14, r0, carry);
MP_SUB_BORROW(r1, a15, r1, carry);
MP_SUB_BORROW(r2, 0, r2, carry);
MP_SUB_BORROW(r3, a9, r3, carry);
MP_SUB_BORROW(r4, a10, r4, carry);
MP_SUB_BORROW(r5, a11, r5, carry);
MP_SUB_BORROW(r6, 0, r6, carry);
MP_SUB_BORROW(r7, a13, r7, carry);
r8 -= carry;
/* reduce the overflows */
while (r8 > 0) {
mp_digit r8_d = r8;
carry = 0;
MP_ADD_CARRY(r0, r8_d, r0, carry);
MP_ADD_CARRY(r1, 0, r1, carry);
MP_ADD_CARRY(r2, 0, r2, carry);
MP_ADD_CARRY(r3, 0 - r8_d, r3, carry);
MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry);
MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry);
MP_ADD_CARRY(r6, 0 - (r8_d + 1), r6, carry);
MP_ADD_CARRY(r7, (r8_d - 1), r7, carry);
r8 = carry;
}
/* reduce the underflows */
while (r8 < 0) {
mp_digit r8_d = -r8;
carry = 0;
MP_SUB_BORROW(r0, r8_d, r0, carry);
MP_SUB_BORROW(r1, 0, r1, carry);
MP_SUB_BORROW(r2, 0, r2, carry);
MP_SUB_BORROW(r3, 0 - r8_d, r3, carry);
MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry);
MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry);
MP_SUB_BORROW(r6, 0 - (r8_d + 1), r6, carry);
MP_SUB_BORROW(r7, (r8_d - 1), r7, carry);
r8 = 0 - 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));
}
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 */
carry = 0;
MP_ADD_CARRY(r1, a5h << 32, r1, carry);
MP_ADD_CARRY(r2, a6, r2, carry);
MP_ADD_CARRY(r3, a7, r3, carry);
r4 = carry;
carry = 0;
MP_ADD_CARRY(r1, a5h << 32, r1, carry);
MP_ADD_CARRY(r2, a6, r2, carry);
MP_ADD_CARRY(r3, a7, r3, carry);
r4 += carry;
/* sum 2 */
carry = 0;
MP_ADD_CARRY(r1, a6l, r1, carry);
MP_ADD_CARRY(r2, a6h | a7l, r2, carry);
MP_ADD_CARRY(r3, a7h, r3, carry);
r4 += carry;
carry = 0;
MP_ADD_CARRY(r1, a6l, r1, carry);
MP_ADD_CARRY(r2, a6h | a7l, r2, carry);
MP_ADD_CARRY(r3, a7h, r3, carry);
r4 += carry;
/* sum 3 */
carry = 0;
MP_ADD_CARRY(r0, a4, r0, carry);
MP_ADD_CARRY(r1, a5l >> 32, r1, carry);
MP_ADD_CARRY(r2, 0, r2, carry);
MP_ADD_CARRY(r3, a7, r3, carry);
r4 += carry;
/* sum 4 */
carry = 0;
MP_ADD_CARRY(r0, a4h | a5l, r0, carry);
MP_ADD_CARRY(r1, a5h | (a6h << 32), r1, carry);
MP_ADD_CARRY(r2, a7, r2, carry);
MP_ADD_CARRY(r3, a6h | a4l, r3, carry);
r4 += carry;
/* diff 5 */
carry = 0;
MP_SUB_BORROW(r0, a5h | a6l, r0, carry);
MP_SUB_BORROW(r1, a6h, r1, carry);
MP_SUB_BORROW(r2, 0, r2, carry);
MP_SUB_BORROW(r3, (a4l >> 32) | a5l, r3, carry);
r4 -= carry;
/* diff 6 */
carry = 0;
MP_SUB_BORROW(r0, a6, r0, carry);
MP_SUB_BORROW(r1, a7, r1, carry);
MP_SUB_BORROW(r2, 0, r2, carry);
MP_SUB_BORROW(r3, a4h | (a5h << 32), r3, carry);
r4 -= carry;
/* diff 7 */
carry = 0;
MP_SUB_BORROW(r0, a6h | a7l, r0, carry);
MP_SUB_BORROW(r1, a7h | a4l, r1, carry);
MP_SUB_BORROW(r2, a4h | a5l, r2, carry);
MP_SUB_BORROW(r3, a6l, r3, carry);
r4 -= carry;
/* diff 8 */
carry = 0;
MP_SUB_BORROW(r0, a7, r0, carry);
MP_SUB_BORROW(r1, a4h << 32, r1, carry);
MP_SUB_BORROW(r2, a5, r2, carry);
MP_SUB_BORROW(r3, a6h << 32, r3, carry);
r4 -= carry;
/* reduce the overflows */
while (r4 > 0) {
mp_digit r4_long = r4;
mp_digit r4l = (r4_long << 32);
carry = 0;
MP_ADD_CARRY(r0, r4_long, r0, carry);
MP_ADD_CARRY(r1, 0 - r4l, r1, carry);
MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry);
MP_ADD_CARRY(r3, r4l - r4_long - 1, r3, carry);
r4 = carry;
}
/* reduce the underflows */
while (r4 < 0) {
mp_digit r4_long = -r4;
mp_digit r4l = (r4_long << 32);
carry = 0;
MP_SUB_BORROW(r0, r4_long, r0, carry);
MP_SUB_BORROW(r1, 0 - r4l, r1, carry);
MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry);
MP_SUB_BORROW(r3, r4l - r4_long - 1, r3, carry);
r4 = 0 - 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.
*/
static 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. */
static 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,258 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecp.h"
#include "mpi.h"
#include "mplogic.h"
#include "mpi-priv.h"
/* 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. */
static 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.
*/
static 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. */
static 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;
}

View File

@ -1,137 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecp.h"
#include "mpi.h"
#include "mplogic.h"
#include "mpi-priv.h"
#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. */
static 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;
} else if (s_mp_cmp(r, &meth->irr) == 0) {
mp_zero(r);
}
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.
*/
static 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. */
static 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. */
static 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));
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;
}

View File

@ -1,308 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecp.h"
#include "mplogic.h"
#include <stdlib.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)
{
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));
MP_CHECKOK(mp_init(&temp));
MP_CHECKOK(mp_init(&tempx));
MP_CHECKOK(mp_init(&tempy));
/* 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));
/* 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));
MP_CHECKOK(mp_init(&accr));
MP_CHECKOK(mp_init(&tmp));
MP_CHECKOK(mp_init(&pxt));
MP_CHECKOK(mp_init(&pyt));
/* 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_CHECKOK(mp_copy(px, &pxt));
MP_CHECKOK(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 = (x^2 + a)*x + b by Horner's rule */
MP_CHECKOK(group->meth->field_sqr(&pxt, &tmp, group->meth));
MP_CHECKOK(group->meth->field_add(&tmp, &group->curvea, &tmp, group->meth));
MP_CHECKOK(group->meth->field_mul(&tmp, &pxt, &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.
*/
MP_CHECKOK(ECPoint_mul(group, &group->order, px, py, &pxt, &pyt));
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;
}

View File

@ -1,513 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecp.h"
#include "mplogic.h"
#include <stdlib.h>
#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));
MP_CHECKOK(mp_init(&z2));
MP_CHECKOK(mp_init(&z3));
/* 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));
MP_CHECKOK(mp_init(&B));
MP_CHECKOK(mp_init(&C));
MP_CHECKOK(mp_init(&D));
MP_CHECKOK(mp_init(&C2));
MP_CHECKOK(mp_init(&C3));
/* 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));
/* 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));
if (mp_cmp_z(&C) == 0) {
/* P == Q or P == -Q */
if (mp_cmp_z(&D) == 0) {
/* P == Q */
/* It is cheaper to double (qx, qy, 1) than (px, py, pz). */
MP_DIGIT(&D, 0) = 1; /* Set D to 1. */
MP_CHECKOK(ec_GFp_pt_dbl_jac(qx, qy, &D, rx, ry, rz, group));
} else {
/* P == -Q */
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
}
goto CLEANUP;
}
/* 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));
MP_CHECKOK(mp_init(&t1));
MP_CHECKOK(mp_init(&M));
MP_CHECKOK(mp_init(&S));
/* P == inf or P == -P */
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES || mp_cmp_z(py) == 0) {
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_SIGN(&group->curvea) == MP_NEG &&
MP_USED(&group->curvea) == 1 &&
MP_DIGIT(&group->curvea, 0) == 3) {
/* 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)
{
mp_err res = MP_OKAY;
mp_int precomp[4][4][2];
mp_int rz;
const mp_int *a, *b;
unsigned 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);
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
}
/* initialize precomputation table */
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
MP_CHECKOK(mp_init(&precomp[i][j][0]));
MP_CHECKOK(mp_init(&precomp[i][j][1]));
}
}
/* 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));
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
for (i = d; i-- > 0;) {
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;
}

View File

@ -1,297 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecp.h"
#include "ecl-priv.h"
#include "mplogic.h"
#include <stdlib.h>
#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.
*
*/
static 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. */
static 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));
/* Check P == Q */
if (mp_cmp(A, px) == 0) {
if (mp_cmp(B, py) == 0) {
/* If Px == Qx && Py == Qy, double P. */
return ec_GFp_pt_dbl_jm(px, py, pz, paz4, rx, ry, rz, raz4,
scratch, group);
}
/* If Px == Qx && Py != Qy, return point at infinity. */
return ec_GFp_pt_set_inf_jac(rx, ry, rz);
}
/* 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)
{
mp_err res = MP_OKAY;
mp_int precomp[16][2], rz, tpx, tpy;
mp_int raz4;
mp_int scratch[MAX_SCRATCH];
signed char *naf = NULL;
int i, orderBitSize = 0;
MP_DIGITS(&rz) = 0;
MP_DIGITS(&raz4) = 0;
MP_DIGITS(&tpx) = 0;
MP_DIGITS(&tpy) = 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));
MP_CHECKOK(mp_init(&tpy));
;
MP_CHECKOK(mp_init(&rz));
MP_CHECKOK(mp_init(&raz4));
for (i = 0; i < 16; i++) {
MP_CHECKOK(mp_init(&precomp[i][0]));
MP_CHECKOK(mp_init(&precomp[i][1]));
}
for (i = 0; i < MAX_SCRATCH; i++) {
MP_CHECKOK(mp_init(&scratch[i]));
}
/* 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 */
naf = (signed char *)malloc(sizeof(signed char) * (orderBitSize + 1));
if (naf == NULL) {
res = MP_MEM;
goto CLEANUP;
}
/* Compute 5NAF */
ec_compute_wNAF(naf, orderBitSize, n, 5);
/* wNAF method */
for (i = orderBitSize; i >= 0; i--) {
/* 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);
}
}
/* 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(&rz);
mp_clear(&raz4);
if (naf) {
memset(naf, 0, orderBitSize + 1);
}
free(naf);
return res;
}

View File

@ -1,154 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* 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"
#include <stdlib.h>
#include <stdio.h>
/* 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;
GFMethod *meth = NULL;
mp_mont_modulus *mmm;
meth = GFMethod_consGFp(irr);
if (meth == NULL)
return NULL;
mmm = (mp_mont_modulus *)malloc(sizeof(mp_mont_modulus));
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;
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));
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(mp_copy(a, r));
MP_CHECKOK(s_mp_lshd(r, MP_USED(&mmm->N)));
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) {
free(meth->extra1);
meth->extra1 = NULL;
}
}

View File

@ -153,30 +153,45 @@ ec_secp256r1_pt_mul(SECItem *X, SECItem *k, SECItem *P)
*/
SECStatus
ec_secp256r1_sign_digest(ECPrivateKey *key, SECItem *signature,
ec_secp256r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature,
const SECItem *digest, const unsigned char *kb,
const unsigned int kblen)
{
SECStatus res = SECSuccess;
if (!key || !signature || !digest || !kb ||
!key->privateValue.data ||
if (!ecPrivKey || !signature || !digest || !kb ||
!ecPrivKey->privateValue.data ||
!signature->data || !digest->data ||
key->ecParams.name != ECCurve_NIST_P256) {
ecPrivKey->ecParams.name != ECCurve_NIST_P256) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
res = SECFailure;
return res;
}
if (key->privateValue.len != 32 ||
kblen == 0 ||
digest->len == 0 ||
signature->len < 64) {
if (kblen == 0 || digest->len == 0 || signature->len < 64) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
res = SECFailure;
return res;
}
// Private keys should be 32 bytes, but some software trims leading zeros,
// and some software produces 33 byte keys with a leading zero. We'll
// accept these variants.
uint8_t padded_key_data[32] = { 0 };
uint8_t *key;
SECItem *privKey = &ecPrivKey->privateValue;
if (privKey->len == 32) {
key = privKey->data;
} else if (privKey->len == 33 && privKey->data[0] == 0) {
key = privKey->data + 1;
} else if (privKey->len < 32) {
memcpy(padded_key_data + 32 - privKey->len, privKey->data, privKey->len);
key = padded_key_data;
} else {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
uint8_t hash[32] = { 0 };
if (digest->len < 32) {
memcpy(hash + 32 - digest->len, digest->data, digest->len);
@ -192,8 +207,7 @@ ec_secp256r1_sign_digest(ECPrivateKey *key, SECItem *signature,
}
bool b = Hacl_P256_ecdsa_sign_p256_without_hash(
signature->data, 32, hash,
key->privateValue.data, nonce);
signature->data, 32, hash, key, nonce);
if (!b) {
PORT_SetError(SEC_ERROR_BAD_KEY);
res = SECFailure;
@ -214,6 +228,9 @@ ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
{
SECStatus res = SECSuccess;
unsigned char _padded_sig_data[64] = { 0 };
unsigned char *sig_r, *sig_s;
if (!key || !signature || !digest ||
!key->publicValue.data ||
!signature->data || !digest->data ||
@ -223,9 +240,10 @@ ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
return res;
}
if (key->publicValue.len != 65 ||
digest->len == 0 ||
signature->len != 64) {
unsigned int olen = key->ecParams.order.len;
if (signature->len == 0 || signature->len % 2 != 0 ||
signature->len > 2 * olen ||
digest->len == 0 || key->publicValue.len != 65) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
res = SECFailure;
return res;
@ -237,6 +255,24 @@ ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
return res;
}
/* P-256 signature has to be 64 bytes long, pad it with 0s if it isn't */
if (signature->len != 64) {
unsigned split = signature->len / 2;
unsigned pad = 32 - split;
unsigned char *o_sig = signature->data;
unsigned char *p_sig = _padded_sig_data;
memcpy(p_sig + pad, o_sig, split);
memcpy(p_sig + 32 + pad, o_sig + split, split);
sig_r = p_sig;
sig_s = p_sig + 32;
} else {
sig_r = signature->data;
sig_s = signature->data + 32;
}
uint8_t hash[32] = { 0 };
if (digest->len < 32) {
memcpy(hash + 32 - digest->len, digest->data, digest->len);
@ -247,7 +283,7 @@ ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
bool b = Hacl_P256_ecdsa_verif_without_hash(
32, hash,
key->publicValue.data + 1,
signature->data, signature->data + 32);
sig_r, sig_s);
if (!b) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
res = SECFailure;

File diff suppressed because it is too large Load Diff

View File

@ -1,228 +0,0 @@
/*-
* MIT License
* -
* Copyright (c) 2020 Luis Rivera-Zamarripa, Jesús-Javier Chi-Domínguez, Billy Bob Brumley
* -
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* -
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* -
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#undef RADIX
#include "ecp.h"
#include "ecp_secp384r1.h"
#include "mpi-priv.h"
#include "mplogic.h"
/*-
* reverse bytes -- total hack
*/
#define MP_BE2LE(a) \
do { \
unsigned char z_bswap; \
z_bswap = a[0]; \
a[0] = a[47]; \
a[47] = z_bswap; \
z_bswap = a[1]; \
a[1] = a[46]; \
a[46] = z_bswap; \
z_bswap = a[2]; \
a[2] = a[45]; \
a[45] = z_bswap; \
z_bswap = a[3]; \
a[3] = a[44]; \
a[44] = z_bswap; \
z_bswap = a[4]; \
a[4] = a[43]; \
a[43] = z_bswap; \
z_bswap = a[5]; \
a[5] = a[42]; \
a[42] = z_bswap; \
z_bswap = a[6]; \
a[6] = a[41]; \
a[41] = z_bswap; \
z_bswap = a[7]; \
a[7] = a[40]; \
a[40] = z_bswap; \
z_bswap = a[8]; \
a[8] = a[39]; \
a[39] = z_bswap; \
z_bswap = a[9]; \
a[9] = a[38]; \
a[38] = z_bswap; \
z_bswap = a[10]; \
a[10] = a[37]; \
a[37] = z_bswap; \
z_bswap = a[11]; \
a[11] = a[36]; \
a[36] = z_bswap; \
z_bswap = a[12]; \
a[12] = a[35]; \
a[35] = z_bswap; \
z_bswap = a[13]; \
a[13] = a[34]; \
a[34] = z_bswap; \
z_bswap = a[14]; \
a[14] = a[33]; \
a[33] = z_bswap; \
z_bswap = a[15]; \
a[15] = a[32]; \
a[32] = z_bswap; \
z_bswap = a[16]; \
a[16] = a[31]; \
a[31] = z_bswap; \
z_bswap = a[17]; \
a[17] = a[30]; \
a[30] = z_bswap; \
z_bswap = a[18]; \
a[18] = a[29]; \
a[29] = z_bswap; \
z_bswap = a[19]; \
a[19] = a[28]; \
a[28] = z_bswap; \
z_bswap = a[20]; \
a[20] = a[27]; \
a[27] = z_bswap; \
z_bswap = a[21]; \
a[21] = a[26]; \
a[26] = z_bswap; \
z_bswap = a[22]; \
a[22] = a[25]; \
a[25] = z_bswap; \
z_bswap = a[23]; \
a[23] = a[24]; \
a[24] = z_bswap; \
} while (0)
static mp_err
point_mul_g_secp384r1_wrap(const mp_int *n, mp_int *out_x,
mp_int *out_y, const ECGroup *group)
{
unsigned char b_x[48];
unsigned char b_y[48];
unsigned char b_n[48];
mp_err res;
ARGCHK(n != NULL && out_x != NULL && out_y != NULL, MP_BADARG);
/* fail on out of range scalars */
if (mpl_significant_bits(n) > 384 || mp_cmp_z(n) != MP_GT)
return MP_RANGE;
MP_CHECKOK(mp_to_fixlen_octets(n, b_n, 48));
MP_BE2LE(b_n);
point_mul_g_secp384r1(b_x, b_y, b_n);
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 48));
MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 48));
CLEANUP:
return res;
}
static mp_err
point_mul_secp384r1_wrap(const mp_int *n, const mp_int *in_x,
const mp_int *in_y, mp_int *out_x,
mp_int *out_y, const ECGroup *group)
{
unsigned char b_x[48];
unsigned char b_y[48];
unsigned char b_n[48];
mp_err res;
ARGCHK(n != NULL && in_x != NULL && in_y != NULL && out_x != NULL &&
out_y != NULL,
MP_BADARG);
/* fail on out of range scalars */
if (mpl_significant_bits(n) > 384 || mp_cmp_z(n) != MP_GT)
return MP_RANGE;
MP_CHECKOK(mp_to_fixlen_octets(n, b_n, 48));
MP_CHECKOK(mp_to_fixlen_octets(in_x, b_x, 48));
MP_CHECKOK(mp_to_fixlen_octets(in_y, b_y, 48));
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_BE2LE(b_n);
point_mul_secp384r1(b_x, b_y, b_n, b_x, b_y);
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 48));
MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 48));
CLEANUP:
return res;
}
static mp_err
point_mul_two_secp384r1_wrap(const mp_int *n1, const mp_int *n2,
const mp_int *in_x,
const mp_int *in_y, mp_int *out_x,
mp_int *out_y,
const ECGroup *group)
{
unsigned char b_x[48];
unsigned char b_y[48];
unsigned char b_n1[48];
unsigned char b_n2[48];
mp_err res;
/* If n2 == NULL or 0, this is just a base-point multiplication. */
if (n2 == NULL || mp_cmp_z(n2) == MP_EQ)
return point_mul_g_secp384r1_wrap(n1, out_x, out_y, group);
/* If n1 == NULL or 0, this is just an arbitary-point multiplication. */
if (n1 == NULL || mp_cmp_z(n1) == MP_EQ)
return point_mul_secp384r1_wrap(n2, in_x, in_y, out_x, out_y, group);
ARGCHK(in_x != NULL && in_y != NULL && out_x != NULL && out_y != NULL,
MP_BADARG);
/* fail on out of range scalars */
if (mpl_significant_bits(n1) > 384 || mp_cmp_z(n1) != MP_GT ||
mpl_significant_bits(n2) > 384 || mp_cmp_z(n2) != MP_GT)
return MP_RANGE;
MP_CHECKOK(mp_to_fixlen_octets(n1, b_n1, 48));
MP_CHECKOK(mp_to_fixlen_octets(n2, b_n2, 48));
MP_CHECKOK(mp_to_fixlen_octets(in_x, b_x, 48));
MP_CHECKOK(mp_to_fixlen_octets(in_y, b_y, 48));
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_BE2LE(b_n1);
MP_BE2LE(b_n2);
point_mul_two_secp384r1(b_x, b_y, b_n1, b_n2, b_x, b_y);
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 48));
MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 48));
CLEANUP:
return res;
}
mp_err
ec_group_set_secp384r1(ECGroup *group, ECCurveName name)
{
if (name == ECCurve_NIST_P384) {
group->base_point_mul = &point_mul_g_secp384r1_wrap;
group->point_mul = &point_mul_secp384r1_wrap;
group->points_mul = &point_mul_two_secp384r1_wrap;
}
return MP_OKAY;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,255 +0,0 @@
/*-
* MIT License
* -
* Copyright (c) 2020 Luis Rivera-Zamarripa, Jesús-Javier Chi-Domínguez, Billy Bob Brumley
* -
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* -
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* -
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#undef RADIX
#include "ecp.h"
#include "ecp_secp521r1.h"
#include "mpi-priv.h"
#include "mplogic.h"
/*-
* reverse bytes -- total hack
*/
#define MP_BE2LE(a) \
do { \
unsigned char z_bswap; \
z_bswap = a[0]; \
a[0] = a[65]; \
a[65] = z_bswap; \
z_bswap = a[1]; \
a[1] = a[64]; \
a[64] = z_bswap; \
z_bswap = a[2]; \
a[2] = a[63]; \
a[63] = z_bswap; \
z_bswap = a[3]; \
a[3] = a[62]; \
a[62] = z_bswap; \
z_bswap = a[4]; \
a[4] = a[61]; \
a[61] = z_bswap; \
z_bswap = a[5]; \
a[5] = a[60]; \
a[60] = z_bswap; \
z_bswap = a[6]; \
a[6] = a[59]; \
a[59] = z_bswap; \
z_bswap = a[7]; \
a[7] = a[58]; \
a[58] = z_bswap; \
z_bswap = a[8]; \
a[8] = a[57]; \
a[57] = z_bswap; \
z_bswap = a[9]; \
a[9] = a[56]; \
a[56] = z_bswap; \
z_bswap = a[10]; \
a[10] = a[55]; \
a[55] = z_bswap; \
z_bswap = a[11]; \
a[11] = a[54]; \
a[54] = z_bswap; \
z_bswap = a[12]; \
a[12] = a[53]; \
a[53] = z_bswap; \
z_bswap = a[13]; \
a[13] = a[52]; \
a[52] = z_bswap; \
z_bswap = a[14]; \
a[14] = a[51]; \
a[51] = z_bswap; \
z_bswap = a[15]; \
a[15] = a[50]; \
a[50] = z_bswap; \
z_bswap = a[16]; \
a[16] = a[49]; \
a[49] = z_bswap; \
z_bswap = a[17]; \
a[17] = a[48]; \
a[48] = z_bswap; \
z_bswap = a[18]; \
a[18] = a[47]; \
a[47] = z_bswap; \
z_bswap = a[19]; \
a[19] = a[46]; \
a[46] = z_bswap; \
z_bswap = a[20]; \
a[20] = a[45]; \
a[45] = z_bswap; \
z_bswap = a[21]; \
a[21] = a[44]; \
a[44] = z_bswap; \
z_bswap = a[22]; \
a[22] = a[43]; \
a[43] = z_bswap; \
z_bswap = a[23]; \
a[23] = a[42]; \
a[42] = z_bswap; \
z_bswap = a[24]; \
a[24] = a[41]; \
a[41] = z_bswap; \
z_bswap = a[25]; \
a[25] = a[40]; \
a[40] = z_bswap; \
z_bswap = a[26]; \
a[26] = a[39]; \
a[39] = z_bswap; \
z_bswap = a[27]; \
a[27] = a[38]; \
a[38] = z_bswap; \
z_bswap = a[28]; \
a[28] = a[37]; \
a[37] = z_bswap; \
z_bswap = a[29]; \
a[29] = a[36]; \
a[36] = z_bswap; \
z_bswap = a[30]; \
a[30] = a[35]; \
a[35] = z_bswap; \
z_bswap = a[31]; \
a[31] = a[34]; \
a[34] = z_bswap; \
z_bswap = a[32]; \
a[32] = a[33]; \
a[33] = z_bswap; \
} while (0)
static mp_err
point_mul_g_secp521r1_wrap(const mp_int *n, mp_int *out_x,
mp_int *out_y, const ECGroup *group)
{
unsigned char b_x[66];
unsigned char b_y[66];
unsigned char b_n[66];
mp_err res;
ARGCHK(n != NULL && out_x != NULL && out_y != NULL, MP_BADARG);
/* fail on out of range scalars */
if (mpl_significant_bits(n) > 521 || mp_cmp_z(n) != MP_GT)
return MP_RANGE;
MP_CHECKOK(mp_to_fixlen_octets(n, b_n, 66));
MP_BE2LE(b_n);
point_mul_g_secp521r1(b_x, b_y, b_n);
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 66));
MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 66));
CLEANUP:
return res;
}
static mp_err
point_mul_secp521r1_wrap(const mp_int *n, const mp_int *in_x,
const mp_int *in_y, mp_int *out_x,
mp_int *out_y, const ECGroup *group)
{
unsigned char b_x[66];
unsigned char b_y[66];
unsigned char b_n[66];
mp_err res;
ARGCHK(n != NULL && in_x != NULL && in_y != NULL && out_x != NULL &&
out_y != NULL,
MP_BADARG);
/* fail on out of range scalars */
if (mpl_significant_bits(n) > 521 || mp_cmp_z(n) != MP_GT)
return MP_RANGE;
MP_CHECKOK(mp_to_fixlen_octets(n, b_n, 66));
MP_CHECKOK(mp_to_fixlen_octets(in_x, b_x, 66));
MP_CHECKOK(mp_to_fixlen_octets(in_y, b_y, 66));
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_BE2LE(b_n);
point_mul_secp521r1(b_x, b_y, b_n, b_x, b_y);
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 66));
MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 66));
CLEANUP:
return res;
}
static mp_err
point_mul_two_secp521r1_wrap(const mp_int *n1, const mp_int *n2,
const mp_int *in_x,
const mp_int *in_y, mp_int *out_x,
mp_int *out_y,
const ECGroup *group)
{
unsigned char b_x[66];
unsigned char b_y[66];
unsigned char b_n1[66];
unsigned char b_n2[66];
mp_err res;
/* If n2 == NULL or 0, this is just a base-point multiplication. */
if (n2 == NULL || mp_cmp_z(n2) == MP_EQ)
return point_mul_g_secp521r1_wrap(n1, out_x, out_y, group);
/* If n1 == NULL or 0, this is just an arbitary-point multiplication. */
if (n1 == NULL || mp_cmp_z(n1) == MP_EQ)
return point_mul_secp521r1_wrap(n2, in_x, in_y, out_x, out_y, group);
ARGCHK(in_x != NULL && in_y != NULL && out_x != NULL && out_y != NULL,
MP_BADARG);
/* fail on out of range scalars */
if (mpl_significant_bits(n1) > 521 || mp_cmp_z(n1) != MP_GT ||
mpl_significant_bits(n2) > 521 || mp_cmp_z(n2) != MP_GT)
return MP_RANGE;
MP_CHECKOK(mp_to_fixlen_octets(n1, b_n1, 66));
MP_CHECKOK(mp_to_fixlen_octets(n2, b_n2, 66));
MP_CHECKOK(mp_to_fixlen_octets(in_x, b_x, 66));
MP_CHECKOK(mp_to_fixlen_octets(in_y, b_y, 66));
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_BE2LE(b_n1);
MP_BE2LE(b_n2);
point_mul_two_secp521r1(b_x, b_y, b_n1, b_n2, b_x, b_y);
MP_BE2LE(b_x);
MP_BE2LE(b_y);
MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 66));
MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 66));
CLEANUP:
return res;
}
mp_err
ec_group_set_secp521r1(ECGroup *group, ECCurveName name)
{
if (name == ECCurve_NIST_P521) {
group->base_point_mul = &point_mul_g_secp521r1_wrap;
group->point_mul = &point_mul_secp521r1_wrap;
group->points_mul = &point_mul_two_secp521r1_wrap;
}
return MP_OKAY;
}

View File

@ -1601,7 +1601,7 @@ freebl_fips_EC_PowerUpSelfTest()
NULL,
ec_params_named, /* arena, type */
/* fieldID */
{ 256, ec_field_GFp, /* size and type */
{ 256, ec_field_plain, /* size and type */
{ { siBuffer, (unsigned char *)p256_prime, sizeof(p256_prime) } }, /* u.prime */
0,
0,

View File

@ -21,27 +21,10 @@
'dsa.c',
'ec.c',
'ecdecode.c',
'ecl/ec_naf.c',
'ecl/ecl.c',
'ecl/ecl_gf.c',
'ecl/ecl_mult.c',
'ecl/ecp_25519.c',
'ecl/ecp_256.c',
'ecl/ecp_256_32.c',
'ecl/ecp_384.c',
'ecl/ecp_521.c',
'ecl/ecp_aff.c',
'ecl/ecp_jac.c',
'ecl/ecp_jm.c',
'ecl/ecp_mont.c',
'ecl/ecp_secp256r1.c',
'ecl/ecp_secp384r1.c',
'ecl/ecp_secp384r1_wrap.c',
'ecl/ecp_secp521r1.c',
'ecl/ecp_secp521r1_wrap.c',
'verified/Hacl_P256.c',
'verified/Hacl_P384.c',
'verified/Hacl_P521.c',
'fipsfreebl.c',
'blinit.c',
'freeblver.c',
@ -71,6 +54,9 @@
'tlsprfalg.c',
'secmpi.c',
'verified/Hacl_Hash_SHA3.c',
'verified/Hacl_P256.c',
'verified/Hacl_P384.c',
'verified/Hacl_P521.c',
'sha3.c',
'shake.c',
'verified/Hacl_Curve25519_51.c',

View File

@ -108,12 +108,8 @@ MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
ECL_HDRS = ecl-exp.h ecl.h ecp.h ecl-priv.h
ECL_SRCS = ecl.c ecl_mult.c ecl_gf.c \
ecp_aff.c ecp_jac.c ecp_mont.c \
ec_naf.c ecp_jm.c ecp_256.c ecp_384.c ecp_521.c \
ecp_256_32.c ecp_25519.c ecp_secp256r1.c ecp_secp384r1.c ecp_secp521r1.c \
ecp_secp384r1_wrap.c ecp_secp521r1_wrap.c
ECL_HDRS = ecl-exp.h ecl.h ecl-priv.h
ECL_SRCS = ecp_25519.c ecp_secp256r1.c ecp_secp384r1.c ecp_secp521r1.c
SHA_SRCS = sha_fast.c
MPCPU_SRCS = mpcpucache.c
VERIFIED_SRCS = $(NULL)

File diff suppressed because it is too large Load Diff

View File

@ -44,10 +44,89 @@ extern "C" {
*******************************************************************************/
/*****************/
/* ECDSA signing */
/*****************/
/**
Create an ECDSA signature WITHOUT hashing first.
This function is intended to receive a hash of the input.
For convenience, we recommend using one of the hash-and-sign combined functions above.
The argument `msg` MUST be at least 32 bytes (i.e. `msg_len >= 32`).
NOTE: The equivalent functions in OpenSSL and Fiat-Crypto both accept inputs
smaller than 32 bytes. These libraries left-pad the input with enough zeroes to
reach the minimum 32 byte size. Clients who need behavior identical to OpenSSL
need to perform the left-padding themselves.
The function returns `true` for successful creation of an ECDSA signature and `false` otherwise.
The outparam `signature` (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64].
The argument `msg` points to `msg_len` bytes of valid memory, i.e., uint8_t[msg_len].
The arguments `private_key` and `nonce` point to 32 bytes of valid memory, i.e., uint8_t[32].
The function also checks whether `private_key` and `nonce` are valid values:
0 < `private_key` < the order of the curve
0 < `nonce` < the order of the curve
*/
bool
Hacl_P384_ecdsa_sign_p384_without_hash(
uint8_t *signature,
uint32_t msg_len,
uint8_t *msg,
uint8_t *private_key,
uint8_t *nonce);
/**********************/
/* ECDSA verification */
/**********************/
/**
Verify an ECDSA signature WITHOUT hashing first.
This function is intended to receive a hash of the input.
For convenience, we recommend using one of the hash-and-verify combined functions above.
The argument `msg` MUST be at least 32 bytes (i.e. `msg_len >= 32`).
The function returns `true` if the signature is valid and `false` otherwise.
The argument `msg` points to `msg_len` bytes of valid memory, i.e., uint8_t[msg_len].
The argument `public_key` (x || y) points to 64 bytes of valid memory, i.e., uint8_t[64].
The arguments `signature_r` and `signature_s` point to 32 bytes of valid memory, i.e., uint8_t[32].
The function also checks whether `public_key` is valid
*/
bool
Hacl_P384_ecdsa_verif_without_hash(
uint32_t msg_len,
uint8_t *msg,
uint8_t *public_key,
uint8_t *signature_r,
uint8_t *signature_s);
/******************/
/* Key validation */
/******************/
/**
Public key validation.
The function returns `true` if a public key is valid and `false` otherwise.
The argument `public_key` points to 64 bytes of valid memory, i.e., uint8_t[64].
The public key (x || y) is valid (with respect to SP 800-56A):
the public key is not the point at infinity, represented as O.
the affine x and y coordinates of the point represented by the public key are
in the range [0, p 1] where p is the prime defining the finite field.
y^2 = x^3 + ax + b where a and b are the coefficients of the curve equation.
The last extract is taken from: https://neilmadden.blog/2017/05/17/so-how-do-you-validate-nist-ecdh-public-keys/
*/
bool Hacl_P384_validate_public_key(uint8_t *public_key);
/**
Private key validation.
@ -60,6 +139,94 @@ Private key validation.
*/
bool Hacl_P384_validate_private_key(uint8_t *private_key);
/*******************************************************************************
Parsing and Serializing public keys.
A public key is a point (x, y) on the P-384 NIST curve.
The point can be represented in the following three ways.
raw = [ x || y ], 64 bytes
uncompressed = [ 0x04 || x || y ], 65 bytes
compressed = [ (0x02 for even `y` and 0x03 for odd `y`) || x ], 33 bytes
*******************************************************************************/
/**
Convert a public key from uncompressed to its raw form.
The function returns `true` for successful conversion of a public key and `false` otherwise.
The outparam `pk_raw` points to 64 bytes of valid memory, i.e., uint8_t[64].
The argument `pk` points to 65 bytes of valid memory, i.e., uint8_t[65].
The function DOESN'T check whether (x, y) is a valid point.
*/
bool Hacl_P384_uncompressed_to_raw(uint8_t *pk, uint8_t *pk_raw);
/**
Convert a public key from compressed to its raw form.
The function returns `true` for successful conversion of a public key and `false` otherwise.
The outparam `pk_raw` points to 64 bytes of valid memory, i.e., uint8_t[64].
The argument `pk` points to 33 bytes of valid memory, i.e., uint8_t[33].
The function also checks whether (x, y) is a valid point.
*/
bool Hacl_P384_compressed_to_raw(uint8_t *pk, uint8_t *pk_raw);
/**
Convert a public key from raw to its uncompressed form.
The outparam `pk` points to 65 bytes of valid memory, i.e., uint8_t[65].
The argument `pk_raw` points to 64 bytes of valid memory, i.e., uint8_t[64].
The function DOESN'T check whether (x, y) is a valid point.
*/
void Hacl_P384_raw_to_uncompressed(uint8_t *pk_raw, uint8_t *pk);
/**
Convert a public key from raw to its compressed form.
The outparam `pk` points to 33 bytes of valid memory, i.e., uint8_t[33].
The argument `pk_raw` points to 64 bytes of valid memory, i.e., uint8_t[64].
The function DOESN'T check whether (x, y) is a valid point.
*/
void Hacl_P384_raw_to_compressed(uint8_t *pk_raw, uint8_t *pk);
/******************/
/* ECDH agreement */
/******************/
/**
Compute the public key from the private key.
The function returns `true` if a private key is valid and `false` otherwise.
The outparam `public_key` points to 64 bytes of valid memory, i.e., uint8_t[64].
The argument `private_key` points to 32 bytes of valid memory, i.e., uint8_t[32].
The private key is valid:
0 < `private_key` < the order of the curve.
*/
bool Hacl_P384_dh_initiator(uint8_t *public_key, uint8_t *private_key);
/**
Execute the diffie-hellmann key exchange.
The function returns `true` for successful creation of an ECDH shared secret and
`false` otherwise.
The outparam `shared_secret` points to 64 bytes of valid memory, i.e., uint8_t[64].
The argument `their_pubkey` points to 64 bytes of valid memory, i.e., uint8_t[64].
The argument `private_key` points to 32 bytes of valid memory, i.e., uint8_t[32].
The function also checks whether `private_key` and `their_pubkey` are valid.
*/
bool
Hacl_P384_dh_responder(uint8_t *shared_secret, uint8_t *their_pubkey, uint8_t *private_key);
#if defined(__cplusplus)
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -35,10 +35,98 @@ extern "C" {
#include "lib_intrinsics.h"
/*******************************************************************************
Verified C library for ECDSA and ECDH functions over the P-521 NIST curve.
This module implements signing and verification, key validation, conversions
between various point representations, and ECDH key agreement.
*******************************************************************************/
/*****************/
/* ECDSA signing */
/*****************/
/**
Create an ECDSA signature WITHOUT hashing first.
This function is intended to receive a hash of the input.
For convenience, we recommend using one of the hash-and-sign combined functions above.
The argument `msg` MUST be at least 66 bytes (i.e. `msg_len >= 66`).
NOTE: The equivalent functions in OpenSSL and Fiat-Crypto both accept inputs
smaller than 66 bytes. These libraries left-pad the input with enough zeroes to
reach the minimum 66 byte size. Clients who need behavior identical to OpenSSL
need to perform the left-padding themselves.
The function returns `true` for successful creation of an ECDSA signature and `false` otherwise.
The outparam `signature` (R || S) points to 132 bytes of valid memory, i.e., uint8_t[132].
The argument `msg` points to `msg_len` bytes of valid memory, i.e., uint8_t[msg_len].
The arguments `private_key` and `nonce` point to 66 bytes of valid memory, i.e., uint8_t[66].
The function also checks whether `private_key` and `nonce` are valid values:
0 < `private_key` < the order of the curve
0 < `nonce` < the order of the curve
*/
bool
Hacl_P521_ecdsa_sign_p521_without_hash(
uint8_t *signature,
uint32_t msg_len,
uint8_t *msg,
uint8_t *private_key,
uint8_t *nonce);
/**********************/
/* ECDSA verification */
/**********************/
/**
Verify an ECDSA signature WITHOUT hashing first.
This function is intended to receive a hash of the input.
For convenience, we recommend using one of the hash-and-verify combined functions above.
The argument `msg` MUST be at least 66 bytes (i.e. `msg_len >= 66`).
The function returns `true` if the signature is valid and `false` otherwise.
The argument `msg` points to `msg_len` bytes of valid memory, i.e., uint8_t[msg_len].
The argument `public_key` (x || y) points to 132 bytes of valid memory, i.e., uint8_t[132].
The arguments `signature_r` and `signature_s` point to 66 bytes of valid memory, i.e., uint8_t[66].
The function also checks whether `public_key` is valid
*/
bool
Hacl_P521_ecdsa_verif_without_hash(
uint32_t msg_len,
uint8_t *msg,
uint8_t *public_key,
uint8_t *signature_r,
uint8_t *signature_s);
/******************/
/* Key validation */
/******************/
/**
Public key validation.
The function returns `true` if a public key is valid and `false` otherwise.
The argument `public_key` points to 132 bytes of valid memory, i.e., uint8_t[132].
The public key (x || y) is valid (with respect to SP 800-56A):
the public key is not the point at infinity, represented as O.
the affine x and y coordinates of the point represented by the public key are
in the range [0, p 1] where p is the prime defining the finite field.
y^2 = x^3 + ax + b where a and b are the coefficients of the curve equation.
The last extract is taken from: https://neilmadden.blog/2017/05/17/so-how-do-you-validate-nist-ecdh-public-keys/
*/
bool Hacl_P521_validate_public_key(uint8_t *public_key);
/**
Private key validation.
@ -51,6 +139,94 @@ Private key validation.
*/
bool Hacl_P521_validate_private_key(uint8_t *private_key);
/*******************************************************************************
Parsing and Serializing public keys.
A public key is a point (x, y) on the P-521 NIST curve.
The point can be represented in the following three ways.
raw = [ x || y ], 132 bytes
uncompressed = [ 0x04 || x || y ], 133 bytes
compressed = [ (0x02 for even `y` and 0x03 for odd `y`) || x ], 33 bytes
*******************************************************************************/
/**
Convert a public key from uncompressed to its raw form.
The function returns `true` for successful conversion of a public key and `false` otherwise.
The outparam `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132].
The argument `pk` points to 133 bytes of valid memory, i.e., uint8_t[133].
The function DOESN'T check whether (x, y) is a valid point.
*/
bool Hacl_P521_uncompressed_to_raw(uint8_t *pk, uint8_t *pk_raw);
/**
Convert a public key from compressed to its raw form.
The function returns `true` for successful conversion of a public key and `false` otherwise.
The outparam `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132].
The argument `pk` points to 33 bytes of valid memory, i.e., uint8_t[33].
The function also checks whether (x, y) is a valid point.
*/
bool Hacl_P521_compressed_to_raw(uint8_t *pk, uint8_t *pk_raw);
/**
Convert a public key from raw to its uncompressed form.
The outparam `pk` points to 133 bytes of valid memory, i.e., uint8_t[133].
The argument `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132].
The function DOESN'T check whether (x, y) is a valid point.
*/
void Hacl_P521_raw_to_uncompressed(uint8_t *pk_raw, uint8_t *pk);
/**
Convert a public key from raw to its compressed form.
The outparam `pk` points to 33 bytes of valid memory, i.e., uint8_t[33].
The argument `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132].
The function DOESN'T check whether (x, y) is a valid point.
*/
void Hacl_P521_raw_to_compressed(uint8_t *pk_raw, uint8_t *pk);
/******************/
/* ECDH agreement */
/******************/
/**
Compute the public key from the private key.
The function returns `true` if a private key is valid and `false` otherwise.
The outparam `public_key` points to 132 bytes of valid memory, i.e., uint8_t[132].
The argument `private_key` points to 66 bytes of valid memory, i.e., uint8_t[66].
The private key is valid:
0 < `private_key` < the order of the curve.
*/
bool Hacl_P521_dh_initiator(uint8_t *public_key, uint8_t *private_key);
/**
Execute the diffie-hellmann key exchange.
The function returns `true` for successful creation of an ECDH shared secret and
`false` otherwise.
The outparam `shared_secret` points to 132 bytes of valid memory, i.e., uint8_t[132].
The argument `their_pubkey` points to 132 bytes of valid memory, i.e., uint8_t[132].
The argument `private_key` points to 66 bytes of valid memory, i.e., uint8_t[66].
The function also checks whether `private_key` and `their_pubkey` are valid.
*/
bool
Hacl_P521_dh_responder(uint8_t *shared_secret, uint8_t *their_pubkey, uint8_t *private_key);
#if defined(__cplusplus)
}
#endif

View File

@ -57,6 +57,10 @@
#define KRML_HOST_IGNORE(x) (void)(x)
#endif
#ifndef KRML_MAYBE_UNUSED_VAR
#define KRML_MAYBE_UNUSED_VAR(x) KRML_HOST_IGNORE(x)
#endif
#ifndef KRML_MAYBE_UNUSED
#if defined(__GNUC__)
#define KRML_MAYBE_UNUSED __attribute__((unused))

View File

@ -409,6 +409,8 @@ class OCSPResponseContext final {
OCSPResponseExtension* singleExtensions;
// ResponseData extensions.
OCSPResponseExtension* responseExtensions;
const ByteString* trailingResponseData; // optional; trailing data to include
// at the end of the ResponseData.
bool includeEmptyExtensions; // If true, include the extension wrapper
// regardless of if there are any actual
// extensions.

View File

@ -131,9 +131,11 @@ CheckIssuer(Input encodedIssuer)
{
// "The issuer field MUST contain a non-empty distinguished name (DN)."
Reader issuer(encodedIssuer);
Input encodedRDNs;
ExpectTagAndGetValue(issuer, der::SEQUENCE, encodedRDNs);
Reader rdns(encodedRDNs);
Reader rdns;
Result rv = der::ExpectTagAndGetValueAtEnd(issuer, der::SEQUENCE, rdns);
if (rv != Success) {
return rv;
}
// Check that the issuer name contains at least one RDN
// (Note: this does not check related grammar rules, such as there being one
// or more AVAs in each RDN, or the values in AVAs not being empty strings)
@ -420,7 +422,7 @@ CheckKeyUsage(EndEntityOrCA endEntityOrCA, const Input* encodedKeyUsage,
Reader input(*encodedKeyUsage);
Reader value;
if (der::ExpectTagAndGetValue(input, der::BIT_STRING, value) != Success) {
if (der::ExpectTagAndGetValueAtEnd(input, der::BIT_STRING, value) != Success) {
return Result::ERROR_INADEQUATE_KEY_USAGE;
}
@ -914,7 +916,7 @@ TLSFeaturesSatisfiedInternal(const Input* requiredTLSFeatures,
const static uint8_t status_request_bytes[] = { status_request };
Reader input(*requiredTLSFeatures);
return der::NestedOf(input, der::SEQUENCE, der::INTEGER,
Result rv = der::NestedOf(input, der::SEQUENCE, der::INTEGER,
der::EmptyAllowed::No, [&](Reader& r) {
if (!r.MatchRest(status_request_bytes)) {
return Result::ERROR_REQUIRED_TLS_FEATURE_MISSING;
@ -926,6 +928,10 @@ TLSFeaturesSatisfiedInternal(const Input* requiredTLSFeatures,
return Result::Success;
});
if (rv != Success) {
return rv;
}
return der::End(input);
}
Result

View File

@ -520,9 +520,14 @@ ResponseData(Reader& input, Context& context,
return rv;
}
return der::OptionalExtensions(input,
der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
ExtensionNotUnderstood);
rv = der::OptionalExtensions(input,
der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
ExtensionNotUnderstood);
if (rv != Success) {
return rv;
}
return der::End(input);
}
// SingleResponse ::= SEQUENCE {

View File

@ -163,6 +163,7 @@ OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time)
, producedAt(time)
, singleExtensions(nullptr)
, responseExtensions(nullptr)
, trailingResponseData(nullptr)
, includeEmptyExtensions(false)
, signatureAlgorithm(sha256WithRSAEncryption())
, badSignature(false)
@ -958,6 +959,9 @@ ResponseData(OCSPResponseContext& context)
value.append(producedAtEncoded);
value.append(responses);
value.append(responseExtensions);
if (context.trailingResponseData) {
value.append(*(context.trailingResponseData));
}
return TLV(der::SEQUENCE, value);
}

View File

@ -1256,3 +1256,17 @@ SECMOD_LockedModuleHasRemovableSlots;
;+ local:
;+ *;
;+};
;+NSS_3.101 { # NSS 3.101 release
;+ global:
HASH_GetHashOidTagByHMACOidTag;
PK11_GetMaxKeyLength;
PK11_ReadDistrustAfterAttribute;
SEC_GetMgfTypeByOidTag;
SEC_PKCS5GetCryptoFromAlgTag;
SEC_PKCS5GetHashAlgorithm;
SEC_PKCS5GetHashFromAlgTag;
SECKEY_EnforceKeySize;
SECKEY_PrivateKeyStrengthInBits;
;+ local:
;+ *;
;+};

View File

@ -22,12 +22,12 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define NSS_VERSION "3.100" _NSS_CUSTOMIZED
#define NSS_VERSION "3.101" _NSS_CUSTOMIZED " Beta"
#define NSS_VMAJOR 3
#define NSS_VMINOR 100
#define NSS_VMINOR 101
#define NSS_VPATCH 0
#define NSS_VBUILD 0
#define NSS_BETA PR_FALSE
#define NSS_BETA PR_TRUE
#ifndef RC_INVOKED
@ -307,8 +307,8 @@ SECStatus NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData);
* NSS_KEY_SIZE_POLICY_FLAGS sets and clears all the flags to the input
* value
* On get it returns all the flags
* NSS_KEY_SIZE_POLICY_SET_FLAGS sets only the flags=1 in theinput value and
* does not affect the other flags
* NSS_KEY_SIZE_POLICY_SET_FLAGS sets only the flags=1 in the input value
* and does not affect the other flags
* On get it returns all the flags
* NSS_KEY_SIZE_POLICY_CLEAR_FLAGS clears only the flags=1 in the input
* value and does not affect the other flags
@ -321,6 +321,8 @@ SECStatus NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData);
#define NSS_KEY_SIZE_POLICY_SSL_FLAG 1
#define NSS_KEY_SIZE_POLICY_VERIFY_FLAG 2
#define NSS_KEY_SIZE_POLICY_SIGN_FLAG 4
#define NSS_KEY_SIZE_POLICY_SMIME_FLAG 8
#define NSS_KEY_SIZE_POLICY_ALL_FLAGS 0x0f
#define NSS_ECC_MIN_KEY_SIZE 0x011

View File

@ -764,9 +764,9 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
if (pkixError != NULL) {
goto loser;
} else {
char *ev = PR_GetEnvSecure("NSS_ENABLE_PKIX_VERIFY");
char *ev = PR_GetEnvSecure("NSS_DISABLE_PKIX_VERIFY");
if (ev && ev[0]) {
CERT_SetUsePKIXForValidation(PR_TRUE);
CERT_SetUsePKIXForValidation(PR_FALSE);
}
}
#endif /* NSS_DISABLE_LIBPKIX */

View File

@ -40,7 +40,7 @@ static struct nssOps nss_ops = {
0xffff,
PR_FALSE,
0,
NSS_KEY_SIZE_POLICY_SSL_FLAG,
NSS_KEY_SIZE_POLICY_ALL_FLAGS,
SSL_ECC_MIN_CURVE_BITS
};

View File

@ -16,6 +16,7 @@
#include "nssrwlk.h"
#include "cert.h"
#include "prerror.h"
#include "nsshash.h"
/* wrappers for implementation in libnssutil3 */
#undef ATOB_AsciiToData
@ -127,6 +128,10 @@
#undef SGN_CopyDigestInfo
#undef SGN_CreateDigestInfo
#undef SGN_DestroyDigestInfo
#undef HASH_GetHashTypeByOidTag
#undef HASH_GetHashOidTagByHashType
#undef HASH_GetHashOidTagByHMACOidTag
#undef HASH_GetHMACOidTagByHashOidTag
void *
PORT_Alloc(size_t bytes)
@ -844,6 +849,30 @@ __nss_InitLock(PZLock **ppLock, nssILockType ltype)
return SECFailure;
}
HASH_HashType
HASH_GetHashTypeByOidTag(SECOidTag hashOid)
{
return HASH_GetHashTypeByOidTag_Util(hashOid);
}
SECOidTag
HASH_GetHashOidTagByHashType(HASH_HashType type)
{
return HASH_GetHashOidTagByHashType_Util(type);
}
SECOidTag
HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid)
{
return HASH_GetHashOidTagByHMACOidTag_Util(hmacOid);
}
SECOidTag
HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid)
{
return HASH_GetHMACOidTagByHashOidTag_Util(hashOid);
}
/* templates duplicated in libnss3 and libnssutil3 */
#undef NSS_Get_SEC_AnyTemplate

View File

@ -550,6 +550,34 @@ SEC_DeletePermCRL(CERTSignedCrl *crl)
return (status == PR_SUCCESS) ? SECSuccess : SECFailure;
}
/* search with email with and without NULL
* The sql database accepts the email with a NULL as it's written,
* the dbm database strips the NULL on write so won't match if
* it's there on find */
static CK_OBJECT_HANDLE
pk11_FindSMimeObjectByTemplate(PK11SlotInfo *slot,
CK_ATTRIBUTE *theTemplate, size_t tsize)
{
CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
CK_ATTRIBUTE *last;
PORT_Assert(tsize != 0);
smimeh = pk11_FindObjectByTemplate(slot, theTemplate, (int)tsize);
if (smimeh != CK_INVALID_HANDLE) {
return smimeh;
}
last = &theTemplate[tsize - 1];
if ((last->type == CKA_NSS_EMAIL) && (last->ulValueLen != 0)) {
CK_ULONG save_len = last->ulValueLen;
last->ulValueLen--;
smimeh = pk11_FindObjectByTemplate(slot, theTemplate, (int)tsize);
last->ulValueLen = save_len; /* restore the original */
return smimeh;
}
return CK_INVALID_HANDLE;
}
/*
* return the certificate associated with a derCert
*/
@ -559,8 +587,8 @@ PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
{
CK_OBJECT_CLASS smimeClass = CKO_NSS_SMIME;
CK_ATTRIBUTE theTemplate[] = {
{ CKA_SUBJECT, NULL, 0 },
{ CKA_CLASS, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_NSS_EMAIL, NULL, 0 },
};
CK_ATTRIBUTE smimeData[] = {
@ -579,15 +607,15 @@ PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
return NULL;
}
PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len);
attrs++;
PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass));
attrs++;
PK11_SETATTRS(attrs, CKA_NSS_EMAIL, emailAddr, strlen(emailAddr));
PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len);
attrs++;
PK11_SETATTRS(attrs, CKA_NSS_EMAIL, emailAddr, strlen(emailAddr) + 1);
attrs++;
if (*slot) {
smimeh = pk11_FindObjectByTemplate(*slot, theTemplate, tsize);
smimeh = pk11_FindSMimeObjectByTemplate(*slot, theTemplate, tsize);
} else {
PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
PR_FALSE, PR_TRUE, NULL);
@ -598,7 +626,7 @@ PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
}
/* loop through all the slots */
for (le = list->head; le; le = le->next) {
smimeh = pk11_FindObjectByTemplate(le->slot, theTemplate, tsize);
smimeh = pk11_FindSMimeObjectByTemplate(le->slot, theTemplate, tsize);
if (smimeh != CK_INVALID_HANDLE) {
*slot = PK11_ReferenceSlot(le->slot);
break;

View File

@ -8,6 +8,7 @@
#include <stddef.h>
#include "seccomon.h"
#include "secder.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
@ -1807,6 +1808,55 @@ PK11_ReadRawAttributes(PLArenaPool *arena, PK11ObjectType objType, void *objSpec
return SECSuccess;
}
SECStatus
PK11_ReadDistrustAfterAttribute(PK11SlotInfo *slot,
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_TYPE type,
/* out */ PRBool *distrusted,
/* out */ PRTime *time)
{
if (!slot || !distrusted || !time) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (type != CKA_NSS_SERVER_DISTRUST_AFTER && type != CKA_NSS_EMAIL_DISTRUST_AFTER) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
// The CKA_NSS_SERVER_DISTRUST_AFTER and CKA_NSS_EMAIL_DISTRUST_AFTER
// attributes have either a 13 byte UTCTime value or a 1 byte value
// (equal to 0) indicating that no distrust after date is set.
unsigned char buf[13] = { 0 };
CK_ATTRIBUTE attr = { .type = type, .pValue = buf, .ulValueLen = sizeof buf };
CK_RV crv;
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, object, &attr, 1);
PK11_ExitSlotMonitor(slot);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
if (attr.ulValueLen == 1 && buf[0] == 0) {
// The distrust after date is not set.
*distrusted = PR_FALSE;
return SECSuccess;
}
if (attr.ulValueLen != sizeof buf) {
// Ensure the date is encoded in the expected 13 byte format.
PORT_SetError(SEC_ERROR_INVALID_TIME);
return SECFailure;
}
*distrusted = PR_TRUE;
SECItem item = { siUTCTime, buf, sizeof buf };
return DER_UTCTimeToTime(time, &item);
}
/*
* return the object handle that matches the template
*/

View File

@ -329,52 +329,98 @@ static const oidValDef curveOptList[] = {
static const oidValDef hashOptList[] = {
/* Hashes */
{ CIPHER_NAME("MD2"), SEC_OID_MD2,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("MD4"), SEC_OID_MD4,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("MD5"), SEC_OID_MD5,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA1"), SEC_OID_SHA1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA224"), SEC_OID_SHA224,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA256"), SEC_OID_SHA256,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA384"), SEC_OID_SHA384,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA512"), SEC_OID_SHA512,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE }
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA3-224"), SEC_OID_SHA3_224,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA3-256"), SEC_OID_SHA3_256,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA3-384"), SEC_OID_SHA3_384,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("SHA3-512"), SEC_OID_SHA3_512,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_PKCS12 }
};
static const oidValDef macOptList[] = {
/* MACs */
{ CIPHER_NAME("HMAC-SHA1"), SEC_OID_HMAC_SHA1, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("HMAC-SHA224"), SEC_OID_HMAC_SHA224, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("HMAC-SHA256"), SEC_OID_HMAC_SHA256, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("HMAC-SHA384"), SEC_OID_HMAC_SHA384, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("HMAC-SHA512"), SEC_OID_HMAC_SHA512, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("HMAC-MD5"), SEC_OID_HMAC_MD5, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("HMAC-MD5"), SEC_OID_HMAC_MD5,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA1"), SEC_OID_HMAC_SHA1,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA224"), SEC_OID_HMAC_SHA224,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA256"), SEC_OID_HMAC_SHA256,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA384"), SEC_OID_HMAC_SHA384,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA512"), SEC_OID_HMAC_SHA512,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA3-224"), SEC_OID_HMAC_SHA3_224,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA3-256"), SEC_OID_HMAC_SHA3_256,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA3-384"), SEC_OID_HMAC_SHA3_384,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("HMAC-SHA3-512"), SEC_OID_HMAC_SHA3_512,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
};
static const oidValDef cipherOptList[] = {
/* Ciphers */
{ CIPHER_NAME("AES128-CBC"), SEC_OID_AES_128_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("AES192-CBC"), SEC_OID_AES_192_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("AES256-CBC"), SEC_OID_AES_256_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("AES128-CBC"), SEC_OID_AES_128_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("AES192-CBC"), SEC_OID_AES_192_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("AES256-CBC"), SEC_OID_AES_256_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("AES128-GCM"), SEC_OID_AES_128_GCM, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("AES192-GCM"), SEC_OID_AES_192_GCM, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("AES256-GCM"), SEC_OID_AES_256_GCM, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("CAMELLIA128-CBC"), SEC_OID_CAMELLIA_128_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("CAMELLIA192-CBC"), SEC_OID_CAMELLIA_192_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("CAMELLIA256-CBC"), SEC_OID_CAMELLIA_256_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("CAMELLIA128-CBC"), SEC_OID_CAMELLIA_128_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("CAMELLIA192-CBC"), SEC_OID_CAMELLIA_192_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("CAMELLIA256-CBC"), SEC_OID_CAMELLIA_256_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("CHACHA20-POLY1305"), SEC_OID_CHACHA20_POLY1305, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("SEED-CBC"), SEC_OID_SEED_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("DES-EDE3-CBC"), SEC_OID_DES_EDE3_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("DES-40-CBC"), SEC_OID_DES_40_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("SEED-CBC"), SEC_OID_SEED_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("DES-EDE3-CBC"), SEC_OID_DES_EDE3_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("DES-40-CBC"), SEC_OID_DES_40_CBC,
NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("DES-CBC"), SEC_OID_DES_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("NULL-CIPHER"), SEC_OID_NULL_CIPHER, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("RC2"), SEC_OID_RC2_CBC, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("RC4"), SEC_OID_RC4, NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("RC2"), SEC_OID_RC2_CBC, NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("RC2-40-CBC"), SEC_OID_RC2_40_CBC, NSS_USE_ALG_IN_SMIME },
{ CIPHER_NAME("RC2-64-CBC"), SEC_OID_RC2_64_CBC, NSS_USE_ALG_IN_SMIME },
{ CIPHER_NAME("RC2-128-CBC"), SEC_OID_RC2_128_CBC, NSS_USE_ALG_IN_SMIME },
{ CIPHER_NAME("RC4"), SEC_OID_RC4, NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
{ CIPHER_NAME("IDEA"), SEC_OID_IDEA_CBC, NSS_USE_ALG_IN_SSL },
};
@ -392,6 +438,14 @@ static const oidValDef kxOptList[] = {
{ CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
};
static const oidValDef smimeKxOptList[] = {
/* Key exchange */
{ CIPHER_NAME("RSA-PKCS"), SEC_OID_PKCS1_RSA_ENCRYPTION, NSS_USE_ALG_IN_SMIME_KX },
{ CIPHER_NAME("RSA-OAEP"), SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION, NSS_USE_ALG_IN_SMIME_KX },
{ CIPHER_NAME("ECDH"), SEC_OID_ECDH_KEA, NSS_USE_ALG_IN_SMIME_KX },
{ CIPHER_NAME("DH"), SEC_OID_X942_DIFFIE_HELMAN_KEY, NSS_USE_ALG_IN_SMIME_KX },
};
static const oidValDef signOptList[] = {
/* Signatures */
{ CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
@ -418,7 +472,8 @@ static const algListsDef algOptLists[] = {
{ hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
{ macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
{ cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
{ kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE },
{ kxOptList, PR_ARRAY_SIZE(kxOptList), "SSL-KX", PR_FALSE },
{ smimeKxOptList, PR_ARRAY_SIZE(smimeKxOptList), "SMIME-KX", PR_TRUE },
{ signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_FALSE },
};
@ -441,6 +496,8 @@ static const optionFreeDef keySizeFlagsList[] = {
{ CIPHER_NAME("KEY-SIZE-SSL"), NSS_KEY_SIZE_POLICY_SSL_FLAG },
{ CIPHER_NAME("KEY-SIZE-SIGN"), NSS_KEY_SIZE_POLICY_SIGN_FLAG },
{ CIPHER_NAME("KEY-SIZE-VERIFY"), NSS_KEY_SIZE_POLICY_VERIFY_FLAG },
{ CIPHER_NAME("KEY-SIZE-SMIME"), NSS_KEY_SIZE_POLICY_SMIME_FLAG },
{ CIPHER_NAME("KEY-SIZE-ALL"), NSS_KEY_SIZE_POLICY_ALL_FLAGS },
};
static const optionFreeDef freeOptList[] = {
@ -464,21 +521,46 @@ static const policyFlagDef policyFlagList[] = {
{ CIPHER_NAME("SSL"), NSS_USE_ALG_IN_SSL },
{ CIPHER_NAME("SSL-KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX },
/* add other key exhanges in the future */
{ CIPHER_NAME("KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX },
{ CIPHER_NAME("KEY-EXCHANGE"), NSS_USE_ALG_IN_KEY_EXCHANGE },
{ CIPHER_NAME("CERT-SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("CMS-SIGNATURE"), NSS_USE_ALG_IN_CMS_SIGNATURE },
{ CIPHER_NAME("CMS-SIGNATURE"), NSS_USE_ALG_IN_SMIME_SIGNATURE },
{ CIPHER_NAME("SMIME-SIGNATURE"), NSS_USE_ALG_IN_SMIME_SIGNATURE },
{ CIPHER_NAME("ALL-SIGNATURE"), NSS_USE_ALG_IN_SIGNATURE },
{ CIPHER_NAME("PKCS12"), NSS_USE_ALG_IN_PKCS12 },
/* only use in allow */
{ CIPHER_NAME("PKCS12-LEGACY"), NSS_USE_ALG_IN_PKCS12_DECRYPT },
/* only use in disallow */
{ CIPHER_NAME("PKCS12-ENCRYPT"), NSS_USE_ALG_IN_PKCS12_ENCRYPT },
{ CIPHER_NAME("SMIME"), NSS_USE_ALG_IN_SMIME },
/* only use in allow, enable */
{ CIPHER_NAME("SMIME-LEGACY"), NSS_USE_ALG_IN_SMIME_LEGACY },
/* only use in disallow, disable */
{ CIPHER_NAME("SMIME-ENCRYPT"), NSS_USE_ALG_IN_SMIME_ENCRYPT },
{ CIPHER_NAME("SMIME-KEY-EXCHANGE"), NSS_USE_ALG_IN_SMIME_KX },
/* only use in allow */
{ CIPHER_NAME("SMIME-KEY-EXCHANGE-LEGACY"), NSS_USE_ALG_IN_SMIME_KX_LEGACY },
/* only use in disallow */
{ CIPHER_NAME("SMIME-KEY-EXCHANGE-ENCRYPT"), NSS_USE_ALG_IN_SMIME_KX_ENCRYPT },
/* sign turns off all signatures, but doesn't change the
* allowance for specific sigantures... for example:
* disallow=sha256/all allow=sha256/signature doesn't allow
* cert-sigantures, where disallow=sha256/all allow=sha256/all-signature
* does.
* however, disallow=sha356/signature and disallow=sha256/all-siganture are
* equivalent in effect */
* allowance for specific signatures... for example:
* disallow=sha256/all allow=sha256/signature
* doesn't allow cert-signatures or sime-signatures, where
* disallow=sha256/all allow=sha256/all-signature
* does. however,
* disallow=sha256/signature
* and
* disallow=sha256/all-signature
* are equivalent in effect */
{ CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_ANY_SIGNATURE },
/* enable/allow algorithms for legacy (read/verify)operations */
{ CIPHER_NAME("LEGACY"), NSS_USE_ALG_IN_PKCS12_DECRYPT |
NSS_USE_ALG_IN_SMIME_LEGACY |
NSS_USE_ALG_IN_SMIME_KX_LEGACY },
/* enable/disable everything */
{ CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX |
NSS_USE_ALG_IN_SIGNATURE },
NSS_USE_ALG_IN_PKCS12 | NSS_USE_ALG_IN_SMIME |
NSS_USE_ALG_IN_SIGNATURE |
NSS_USE_ALG_IN_SMIME_KX },
{ CIPHER_NAME("NONE"), 0 }
};
@ -560,6 +642,9 @@ secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,
*result = val;
return SECSuccess;
}
if (policyValueLength == 0) {
return SECFailure;
}
/* handle any ssl strings */
for (i = 0; i < PR_ARRAY_SIZE(sslOptList); i++) {
if (policyValueLength == sslOptList[i].name_size &&
@ -572,7 +657,7 @@ secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,
/* handle key_size flags. Each flag represents a bit, which
* gets or'd together. They can be separated by , | or + */
val = 0;
while (*policyValue) {
while (policyValueLength > 0) {
PRBool found = PR_FALSE;
for (i = 0; i < PR_ARRAY_SIZE(keySizeFlagsList); i++) {
if (PORT_Strncasecmp(keySizeFlagsList[i].name, policyValue,
@ -580,6 +665,7 @@ secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,
val |= keySizeFlagsList[i].option;
found = PR_TRUE;
policyValue += keySizeFlagsList[i].name_size;
policyValueLength -= keySizeFlagsList[i].name_size;
break;
}
}
@ -588,6 +674,7 @@ secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,
}
if (*policyValue == ',' || *policyValue == '|' || *policyValue == '+') {
policyValue++;
policyValueLength--;
}
}
*result = val;
@ -607,6 +694,59 @@ typedef enum {
NSS_ENABLE
} NSSPolicyOperation;
/* Enable/Disable only apply to SSL cipher suites and S/MIME symetric algorithms.
* Enable/Disable is implemented by clearing the DEFAULT_NOT_VALID
* flag, then setting the NSS_USE_DEFAULT_SSL_ENABLE and
* NSS_USE_DEFAULT_SMIME_ENABLE flags to the correct value. The ssl
* policy code will then sort out what to set based on ciphers and
* cipher suite values and the smime policy code will sort
* out which ciphers to include in capabilities based on these values */
static SECStatus
secmod_setDefault(SECOidTag oid, NSSPolicyOperation operation,
PRUint32 value)
{
SECStatus rv = SECSuccess;
PRUint32 policy;
PRUint32 useDefault = 0;
PRUint32 set = 0;
/* we always clear the default not valid flag as this operation will
* make the defaults valid */
PRUint32 clear = NSS_USE_DEFAULT_NOT_VALID;
/* what values are we trying to change */
/* if either SSL or SSL_KX is set, enable SSL */
if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) {
useDefault |= NSS_USE_DEFAULT_SSL_ENABLE;
}
/* only bulk ciphers are configured as enable in S/MIME, only
* enable them if both SMIME bits are set */
if ((value & NSS_USE_ALG_IN_SMIME) == NSS_USE_ALG_IN_SMIME) {
useDefault |= NSS_USE_DEFAULT_SMIME_ENABLE;
}
/* on disable we clear, on enable we set */
if (operation == NSS_DISABLE) {
clear |= useDefault;
} else {
/* we also turn the cipher on by policy if we enable it,
* so include the policy bits */
set |= value | useDefault;
}
/* if we haven't set the not valid flag yet, then we need to
* clear any of the other bits we aren't actually setting as well.
*/
rv = NSS_GetAlgorithmPolicy(oid, &policy);
if (rv != SECSuccess) {
return rv;
}
if (policy & NSS_USE_DEFAULT_NOT_VALID) {
clear |= ((NSS_USE_DEFAULT_SSL_ENABLE | NSS_USE_DEFAULT_SMIME_ENABLE) &
~set);
}
return NSS_SetAlgorithmPolicy(oid, set, clear);
}
/* apply the operator specific policy */
SECStatus
secmod_setPolicyOperation(SECOidTag oid, NSSPolicyOperation operation,
@ -622,25 +762,9 @@ secmod_setPolicyOperation(SECOidTag oid, NSSPolicyOperation operation,
/* set the requested policy bits */
rv = NSS_SetAlgorithmPolicy(oid, value, 0);
break;
/* enable/disable only apply to SSL cipher suites (future S/MIME).
* Enable/disable is implemented by clearing the DEFAULT_NOT_VALID
* flag, then setting the NSS_USE_DEFAULT_SSL_ENABLE flag to the
* correct value. The ssl policy code will then sort out what to
* set based on ciphers and cipher suite values.*/
case NSS_DISABLE:
if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) {
/* clear not valid and enable */
rv = NSS_SetAlgorithmPolicy(oid, 0,
NSS_USE_DEFAULT_NOT_VALID |
NSS_USE_DEFAULT_SSL_ENABLE);
}
break;
case NSS_ENABLE:
if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) {
/* set enable, clear not valid. NOTE: enable implies allow! */
rv = NSS_SetAlgorithmPolicy(oid, value | NSS_USE_DEFAULT_SSL_ENABLE,
NSS_USE_DEFAULT_NOT_VALID);
}
rv = secmod_setDefault(oid, operation, value);
break;
default:
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
@ -819,7 +943,7 @@ secmod_sanityCheckCryptoPolicy(void)
if ((algOpt->val & NSS_USE_ALG_IN_SSL_KX) && (value & NSS_USE_ALG_IN_SSL_KX)) {
++num_kx_enabled;
anyEnabled = PR_TRUE;
fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for KX\n", algOpt->name);
fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL-KX\n", algOpt->name);
}
if ((algOpt->val & NSS_USE_ALG_IN_SSL) && (value & NSS_USE_ALG_IN_SSL)) {
++num_ssl_enabled;

View File

@ -133,6 +133,37 @@ sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm)
return SEC_OID_UNKNOWN;
}
/*
* only gets the tag from PKCS5v1 or PKCS12pbe.
* PKCS5v2 requires the algid to get the full thing
*/
SECOidTag
SEC_PKCS5GetHashFromAlgTag(SECOidTag algtag)
{
switch (algtag) {
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
return SEC_OID_SHA1;
case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
return SEC_OID_MD5;
case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
return SEC_OID_MD2;
default:
break;
}
return SEC_OID_UNKNOWN;
}
/*
* get a new PKCS5 V2 Parameter from the algorithm id.
* if arena is passed in, use it, otherwise create a new arena.
@ -178,6 +209,69 @@ sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param)
}
}
/* maps crypto algorithm from PBE algorithm.
*/
SECOidTag
SEC_PKCS5GetHashAlgorithm(SECAlgorithmID *algid)
{
SECOidTag pbeAlg;
SECOidTag hashAlg = SEC_OID_UNKNOWN;
PLArenaPool *arena = NULL;
if (algid == NULL)
return SEC_OID_UNKNOWN;
pbeAlg = SECOID_GetAlgorithmTag(algid);
/* if we are using a PKCS 5v2 algorithm, get the hash from the parameters */
if ((pbeAlg == SEC_OID_PKCS5_PBES2) ||
(pbeAlg == SEC_OID_PKCS5_PBMAC1)) {
SEC_PKCS5PBEParameter p5_param;
sec_pkcs5V2Parameter *pbeV2_param;
SECOidTag kdfAlg;
SECStatus rv;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (arena == NULL) {
goto loser;
}
pbeV2_param = sec_pkcs5_v2_get_v2_param(arena, algid);
if (pbeV2_param == NULL) {
goto loser;
}
kdfAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
/* sanity check, they should all be PBKDF2 here */
if (kdfAlg != SEC_OID_PKCS5_PBKDF2) {
goto loser;
}
PORT_Memset(&p5_param, 0, sizeof(p5_param));
rv = SEC_ASN1DecodeItem(arena, &p5_param,
SEC_PKCS5V2PBEParameterTemplate,
&pbeV2_param->pbeAlgId.parameters);
if (rv != SECSuccess) {
goto loser;
}
/* if the prf does not exist, it defaults to SHA1 */
hashAlg = SEC_OID_SHA1;
if (p5_param.pPrfAlgId &&
p5_param.pPrfAlgId->algorithm.data != 0) {
hashAlg = HASH_GetHashOidTagByHMACOidTag(
SECOID_GetAlgorithmTag(p5_param.pPrfAlgId));
}
} else {
return SEC_PKCS5GetHashFromAlgTag(pbeAlg);
}
loser:
if (arena != NULL) {
PORT_FreeArena(arena, PR_FALSE);
}
return hashAlg;
}
/* maps crypto algorithm from PBE algorithm.
*/
SECOidTag
@ -207,6 +301,21 @@ SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
return cipherAlg;
}
/*
* only gets the tag from PKCS5v1 or PKCS12pbe.
* PKCS5v2 requires the algid to get the full thing
*/
SECOidTag
SEC_PKCS5GetCryptoFromAlgTag(SECOidTag algtag)
{
SECOidTag cipherAlg;
cipherAlg = sec_pkcs5GetCryptoFromAlgTag(algtag);
if (cipherAlg == SEC_OID_PKCS5_PBKDF2) {
return SEC_OID_UNKNOWN;
}
return cipherAlg;
}
/* check to see if an oid is a pbe algorithm
*/
PRBool
@ -782,7 +891,7 @@ pbe_PK11AlgidToParam(SECAlgorithmID *algid, SECItem *mech)
unsigned char *pSalt = NULL;
CK_ULONG iterations;
int paramLen = 0;
int iv_len;
int iv_len = -1;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (arena == NULL) {

Some files were not shown because too many files have changed in this diff Show More