mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1894459 - land NSS a4c9d2760c66 UPGRADE_NSS_RELEASE, r=keeler
Differential Revision: https://phabricator.services.mozilla.com/D212150
This commit is contained in:
parent
dc8279def2
commit
4d4015d3c2
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
NSS_3_100_RTM
|
||||
a4c9d2760c66
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
NSS_3_99_BRANCH
|
||||
NSS_3_100_BRANCH
|
||||
|
@ -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"]
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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",
|
||||
|
@ -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})`
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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"]
|
@ -1 +0,0 @@
|
||||
0.1.5
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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, ¶m.salt, "Salt", level + 1);
|
||||
SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
|
||||
level + 1);
|
||||
SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level + 1);
|
||||
SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF algorithm", level + 1);
|
||||
if (param.keyLength.data != NULL) {
|
||||
SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level + 1);
|
||||
}
|
||||
if (param.kdfAlg.algorithm.data != NULL) {
|
||||
SECU_PrintAlgorithmID(out, ¶m.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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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':
|
||||
|
@ -10,3 +10,4 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header 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>
|
||||
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
'variables': {
|
||||
'debug_optimization_level': '2',
|
||||
},
|
||||
'cflags_cc': [
|
||||
'-Wno-vla-extension',
|
||||
],
|
||||
'target_conditions': [
|
||||
[ '_type=="executable"', {
|
||||
'libraries!': [
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
@ -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
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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:
|
||||
|
@ -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.
|
@ -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;
|
||||
}
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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_ */
|
@ -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"
|
||||
|
@ -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
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
@ -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
@ -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;
|
||||
}
|
@ -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,
|
||||
|
@ -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',
|
||||
|
@ -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
@ -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
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
;+ *;
|
||||
;+};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user