Update NSS to 3.35-RTM

This commit is contained in:
wolfbeast 2018-02-23 11:04:39 +01:00 • committed by Roy Tam
commit 66dd670b60
388 changed files with 39075 additions and 20752 deletions

View file

@ -703,14 +703,19 @@ CERT_GetOidString(const SECItem* oid)
return NULL;
}
/* If the OID has length 1, we bail. */
if (oid->len < 2) {
return NULL;
}
/* first will point to the next sequence of bytes to decode */
first = (PRUint8*)oid->data;
/* stop points to one past the legitimate data */
stop = &first[oid->len];
/*
* Check for our pseudo-encoded single-digit OIDs
*/
* Check for our pseudo-encoded single-digit OIDs
*/
if ((*first == 0x80) && (2 == oid->len)) {
/* Funky encoding. The second byte is the number */
rvString = PR_smprintf("%lu", (PRUint32)first[1]);
@ -728,6 +733,10 @@ CERT_GetOidString(const SECItem* oid)
break;
}
}
/* There's no first bit set, so this isn't valid. Bail.*/
if (last == stop) {
goto unsupported;
}
bytesBeforeLast = (unsigned int)(last - first);
if (bytesBeforeLast <= 3U) { /* 0-28 bit number */
PRUint32 n = 0;
@ -748,12 +757,12 @@ CERT_GetOidString(const SECItem* oid)
CASE(2, 0x7f);
CASE(1, 0x7f);
case 0:
n |=
last[0] & 0x7f;
n |= last[0] & 0x7f;
break;
}
if (last[0] & 0x80)
if (last[0] & 0x80) {
goto unsupported;
}
if (!rvString) {
/* This is the first number.. decompose it */
@ -1305,8 +1314,7 @@ CERT_GetCertificateEmailAddress(CERTCertificate* cert)
}
} else if (current->type == certRFC822Name) {
rawEmailAddr =
(char*)PORT_ArenaZAlloc(cert->arena, current->name.other.len +
1);
(char*)PORT_ArenaZAlloc(cert->arena, current->name.other.len + 1);
if (!rawEmailAddr) {
goto finish;
}

View file

@ -504,6 +504,8 @@ extern CERTCertificate *CERT_FindCertByKeyID(CERTCertDBHandle *handle,
*/
extern CERTCertificate *CERT_FindCertByIssuerAndSN(
CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN);
extern CERTCertificate *CERT_FindCertByIssuerAndSNCX(
CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN, void *wincx);
/*
** Find a certificate in the database by a subject key ID
@ -547,6 +549,9 @@ CERTCertificate *CERT_FindCertByEmailAddr(CERTCertDBHandle *handle,
*/
CERTCertificate *CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle,
const char *name);
CERTCertificate *CERT_FindCertByNicknameOrEmailAddrCX(CERTCertDBHandle *handle,
const char *name,
void *wincx);
/*
** Find a certificate in the database by a email address or nickname
@ -555,6 +560,9 @@ CERTCertificate *CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle,
*/
CERTCertificate *CERT_FindCertByNicknameOrEmailAddrForUsage(
CERTCertDBHandle *handle, const char *name, SECCertUsage lookingForUsage);
CERTCertificate *CERT_FindCertByNicknameOrEmailAddrForUsageCX(
CERTCertDBHandle *handle, const char *name, SECCertUsage lookingForUsage,
void *wincx);
/*
** Find a certificate in the database by a digest of a subject public key

View file

@ -1192,6 +1192,7 @@ CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage)
case rsaKey:
requiredUsage |= KU_KEY_ENCIPHERMENT;
break;
case rsaPssKey:
case dsaKey:
requiredUsage |= KU_DIGITAL_SIGNATURE;
break;

View file

@ -1294,8 +1294,7 @@ DPCache_AddCRL(CRLDPCache* cache, CachedCrl* newcrl, PRBool* added)
}
}
newcrls = (CachedCrl**)PORT_Realloc(cache->crls, (cache->ncrls + 1) *
sizeof(CachedCrl*));
newcrls = (CachedCrl**)PORT_Realloc(cache->crls, (cache->ncrls + 1) * sizeof(CachedCrl*));
if (!newcrls) {
return SECFailure;
}

View file

@ -457,15 +457,15 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
return CERT_NewTempCertificate(handle, derCert, nickname, isperm, copyDER);
}
/* maybe all the wincx's should be some const for internal token login? */
CERTCertificate *
CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
CERTIssuerAndSN *issuerAndSN)
static CERTCertificate *
common_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
CERTIssuerAndSN *issuerAndSN,
void *wincx)
{
PK11SlotInfo *slot;
CERTCertificate *cert;
cert = PK11_FindCertByIssuerAndSN(&slot, issuerAndSN, NULL);
cert = PK11_FindCertByIssuerAndSN(&slot, issuerAndSN, wincx);
if (cert && slot) {
PK11_FreeSlot(slot);
}
@ -473,6 +473,23 @@ CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
return cert;
}
/* maybe all the wincx's should be some const for internal token login? */
CERTCertificate *
CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
CERTIssuerAndSN *issuerAndSN)
{
return common_FindCertByIssuerAndSN(handle, issuerAndSN, NULL);
}
/* maybe all the wincx's should be some const for internal token login? */
CERTCertificate *
CERT_FindCertByIssuerAndSNCX(CERTCertDBHandle *handle,
CERTIssuerAndSN *issuerAndSN,
void *wincx)
{
return common_FindCertByIssuerAndSN(handle, issuerAndSN, wincx);
}
static NSSCertificate *
get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp)
{
@ -587,7 +604,8 @@ CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert)
static CERTCertificate *
common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
const char *name, PRBool anyUsage,
SECCertUsage lookingForUsage)
SECCertUsage lookingForUsage,
void *wincx)
{
NSSCryptoContext *cc;
NSSCertificate *c, *ct;
@ -620,7 +638,7 @@ common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
}
if (anyUsage) {
cert = PK11_FindCertFromNickname(name, NULL);
cert = PK11_FindCertFromNickname(name, wincx);
} else {
if (ct) {
/* Does ct really have the required usage? */
@ -632,7 +650,7 @@ common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
}
}
certlist = PK11_FindCertsFromNickname(name, NULL);
certlist = PK11_FindCertsFromNickname(name, wincx);
if (certlist) {
SECStatus rv =
CERT_FilterCertListByUsage(certlist, lookingForUsage, PR_FALSE);
@ -659,7 +677,15 @@ CERTCertificate *
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
{
return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_TRUE,
0);
0, NULL);
}
CERTCertificate *
CERT_FindCertByNicknameOrEmailAddrCX(CERTCertDBHandle *handle, const char *name,
void *wincx)
{
return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_TRUE,
0, wincx);
}
CERTCertificate *
@ -668,7 +694,17 @@ CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
SECCertUsage lookingForUsage)
{
return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_FALSE,
lookingForUsage);
lookingForUsage, NULL);
}
CERTCertificate *
CERT_FindCertByNicknameOrEmailAddrForUsageCX(CERTCertDBHandle *handle,
const char *name,
SECCertUsage lookingForUsage,
void *wincx)
{
return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_FALSE,
lookingForUsage, wincx);
}
static void

File diff suppressed because it is too large Load diff

View file

@ -46,8 +46,8 @@
* It's recommend to switch back to 0 after having reached version 98/99.
*/
#define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 16
#define NSS_BUILTINS_LIBRARY_VERSION "2.16"
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 22
#define NSS_BUILTINS_LIBRARY_VERSION "2.22"
/* These version numbers detail the semantic changes to the ckfw engine. */
#define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1

View file

@ -331,8 +331,7 @@ collect_class(
nss_ZFreeIf(keyProvInfo);
if (provName &&
(strncmp(provName, "Microsoft", sizeof("Microsoft") -
1) != 0)) {
(strncmp(provName, "Microsoft", sizeof("Microsoft") - 1) != 0)) {
continue;
}
} else {

View file

@ -59,6 +59,14 @@ extern SECItem *DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len);
*/
extern SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *privKey);
/*
** Create a new signature context from an algorithmID.
** "alg" the signature algorithm to use
** "privKey" the private key to use
*/
extern SGNContext *SGN_NewContextWithAlgorithmID(SECAlgorithmID *alg,
SECKEYPrivateKey *privKey);
/*
** Destroy a signature-context object
** "cx" the object
@ -105,6 +113,21 @@ extern SECStatus SEC_SignData(SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid);
/*
** Sign a single block of data using private key encryption and given
** signature/hash algorithm with parameters from an algorithmID.
** "result" the final signature data (memory is allocated)
** "buf" the input data to sign
** "len" the amount of data to sign
** "pk" the private key to encrypt with
** "algid" the signature/hash algorithm to sign with
** (must be compatible with the key type).
*/
extern SECStatus SEC_SignDataWithAlgorithmID(SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk,
SECAlgorithmID *algid);
/*
** Sign a pre-digested block of data using private key encryption, encoding
** The given signature/hash algorithm.
@ -131,6 +154,27 @@ extern SECStatus SEC_DerSignData(PLArenaPool *arena, SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid);
/*
** DER sign a single block of data using private key encryption and
** the given signature/hash algorithm with parameters from an
** algorithmID. This routine first computes a digital signature using
** SEC_SignData, then wraps it with an CERTSignedData and then der
** encodes the result.
** "arena" is the memory arena to use to allocate data from
** "result" the final der encoded data (memory is allocated)
** "buf" the input data to sign
** "len" the amount of data to sign
** "pk" the private key to encrypt with
** "algid" the signature/hash algorithm to sign with
** (must be compatible with the key type).
*/
extern SECStatus SEC_DerSignDataWithAlgorithmID(PLArenaPool *arena,
SECItem *result,
const unsigned char *buf,
int len,
SECKEYPrivateKey *pk,
SECAlgorithmID *algid);
/*
** Destroy a signed-data object.
** "sd" the object
@ -146,6 +190,23 @@ extern void SEC_DestroySignedData(CERTSignedData *sd, PRBool freeit);
extern SECOidTag SEC_GetSignatureAlgorithmOidTag(KeyType keyType,
SECOidTag hashAlgTag);
/*
** Create algorithm parameters for signing. Return a new item
** allocated from arena, or NULL on failure.
** "arena" is the memory arena to use to allocate data from
** "result" the encoded parameters (memory is allocated)
** "signAlgTag" is the signing algorithm
** "hashAlgTag" is the preferred hash algorithm
** "params" is the default parameters
** "key" is the private key
*/
extern SECItem *SEC_CreateSignatureAlgorithmParameters(PLArenaPool *arena,
SECItem *result,
SECOidTag signAlgTag,
SECOidTag hashAlgTag,
const SECItem *params,
const SECKEYPrivateKey *key);
/****************************************/
/*
** Signature verification operations

View file

@ -17,6 +17,9 @@ KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
SECStatus sec_RSAPSSParamsToMechanism(CK_RSA_PKCS_PSS_PARAMS *mech,
const SECKEYRSAPSSParams *params);
SEC_END_PROTOS
#endif /* _KEYHI_H_ */

View file

@ -221,8 +221,7 @@ SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *c
PK11_ATTR_SESSION |
PK11_ATTR_INSENSITIVE |
PK11_ATTR_PUBLIC,
CKF_DERIVE, CKF_DERIVE |
CKF_SIGN,
CKF_DERIVE, CKF_DERIVE | CKF_SIGN,
cx);
if (!privk)
privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
@ -230,8 +229,7 @@ SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *c
PK11_ATTR_SESSION |
PK11_ATTR_SENSITIVE |
PK11_ATTR_PRIVATE,
CKF_DERIVE, CKF_DERIVE |
CKF_SIGN,
CKF_DERIVE, CKF_DERIVE | CKF_SIGN,
cx);
PK11_FreeSlot(slot);
@ -1048,6 +1046,7 @@ SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
switch (pubk->keyType) {
case rsaKey:
case rsaPssKey:
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
case dsaKey:
@ -1974,3 +1973,118 @@ SECKEY_GetECCOid(const SECKEYECParams *params)
return oidData->offset;
}
static CK_MECHANISM_TYPE
sec_GetHashMechanismByOidTag(SECOidTag tag)
{
switch (tag) {
case SEC_OID_SHA512:
return CKM_SHA512;
case SEC_OID_SHA384:
return CKM_SHA384;
case SEC_OID_SHA256:
return CKM_SHA256;
case SEC_OID_SHA224:
return CKM_SHA224;
case SEC_OID_SHA1:
return CKM_SHA_1;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return CKM_INVALID_MECHANISM;
}
}
static CK_RSA_PKCS_MGF_TYPE
sec_GetMgfTypeByOidTag(SECOidTag tag)
{
switch (tag) {
case SEC_OID_SHA512:
return CKG_MGF1_SHA512;
case SEC_OID_SHA384:
return CKG_MGF1_SHA384;
case SEC_OID_SHA256:
return CKG_MGF1_SHA256;
case SEC_OID_SHA224:
return CKG_MGF1_SHA224;
case SEC_OID_SHA1:
return CKG_MGF1_SHA1;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return 0;
}
}
SECStatus
sec_RSAPSSParamsToMechanism(CK_RSA_PKCS_PSS_PARAMS *mech,
const SECKEYRSAPSSParams *params)
{
SECStatus rv = SECSuccess;
SECOidTag hashAlgTag;
unsigned long saltLength;
unsigned long trailerField;
PORT_Memset(mech, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS));
if (params->hashAlg) {
hashAlgTag = SECOID_GetAlgorithmTag(params->hashAlg);
} else {
hashAlgTag = SEC_OID_SHA1; /* default, SHA-1 */
}
mech->hashAlg = sec_GetHashMechanismByOidTag(hashAlgTag);
if (mech->hashAlg == CKM_INVALID_MECHANISM) {
return SECFailure;
}
if (params->maskAlg) {
SECAlgorithmID maskHashAlg;
SECOidTag maskHashAlgTag;
PORTCheapArenaPool tmpArena;
if (SECOID_GetAlgorithmTag(params->maskAlg) != SEC_OID_PKCS1_MGF1) {
/* only MGF1 is known to PKCS#11 */
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &maskHashAlg,
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
&params->maskAlg->parameters);
PORT_DestroyCheapArena(&tmpArena);
if (rv != SECSuccess) {
return rv;
}
maskHashAlgTag = SECOID_GetAlgorithmTag(&maskHashAlg);
mech->mgf = sec_GetMgfTypeByOidTag(maskHashAlgTag);
if (mech->mgf == 0) {
return SECFailure;
}
} else {
mech->mgf = CKG_MGF1_SHA1; /* default, MGF1 with SHA-1 */
}
if (params->saltLength.data) {
rv = SEC_ASN1DecodeInteger((SECItem *)&params->saltLength, &saltLength);
if (rv != SECSuccess) {
return rv;
}
} else {
saltLength = 20; /* default, 20 */
}
mech->sLen = saltLength;
if (params->trailerField.data) {
rv = SEC_ASN1DecodeInteger((SECItem *)&params->trailerField, &trailerField);
if (rv != SECSuccess) {
return rv;
}
if (trailerField != 1) {
/* the value must be 1, which represents the trailer field
* with hexadecimal value 0xBC */
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
}
return rv;
}

View file

@ -22,10 +22,11 @@ struct SGNContextStr {
void *hashcx;
const SECHashObject *hashobj;
SECKEYPrivateKey *key;
SECItem *params;
};
SGNContext *
SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
static SGNContext *
sgn_NewContext(SECOidTag alg, SECItem *params, SECKEYPrivateKey *key)
{
SGNContext *cx;
SECOidTag hashalg, signalg;
@ -40,7 +41,7 @@ SGN_NewContext(SECOidTag alg, 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, NULL, &signalg, &hashalg);
rv = sec_DecodeSigAlg(NULL, alg, params, &signalg, &hashalg);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return 0;
@ -49,7 +50,8 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
/* verify our key type */
if (key->keyType != keyType &&
!((key->keyType == dsaKey) && (keyType == fortezzaKey))) {
!((key->keyType == dsaKey) && (keyType == fortezzaKey)) &&
!((key->keyType == rsaKey) && (keyType == rsaPssKey))) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return 0;
}
@ -59,10 +61,24 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
cx->hashalg = hashalg;
cx->signalg = signalg;
cx->key = key;
cx->params = params;
}
return cx;
}
SGNContext *
SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
{
return sgn_NewContext(alg, NULL, key);
}
SGNContext *
SGN_NewContextWithAlgorithmID(SECAlgorithmID *alg, SECKEYPrivateKey *key)
{
SECOidTag tag = SECOID_GetAlgorithmTag(alg);
return sgn_NewContext(tag, &alg->parameters, key);
}
void
SGN_DestroyContext(SGNContext *cx, PRBool freeit)
{
@ -148,6 +164,7 @@ SGN_End(SGNContext *cx, SECItem *result)
result->data = 0;
digder.data = 0;
sigitem.data = 0;
/* Finish up digest function */
if (cx->hashcx == NULL) {
@ -156,7 +173,8 @@ SGN_End(SGNContext *cx, SECItem *result)
}
(*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));
if (privKey->keyType == rsaKey) {
if (privKey->keyType == rsaKey &&
cx->signalg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
@ -200,26 +218,65 @@ SGN_End(SGNContext *cx, SECItem *result)
goto loser;
}
rv = PK11_Sign(privKey, &sigitem, &digder);
if (rv != SECSuccess) {
PORT_Free(sigitem.data);
sigitem.data = NULL;
goto loser;
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) {
SECKEYRSAPSSParams params;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
rv = SECFailure;
goto loser;
}
PORT_Memset(&params, 0, sizeof(params));
rv = SEC_QuickDERDecodeItem(arena, &params,
SECKEY_RSAPSSParamsTemplate,
cx->params);
if (rv != SECSuccess) {
goto loser;
}
rv = sec_RSAPSSParamsToMechanism(&mech, &params);
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,
&sigitem, &digder);
if (rv != SECSuccess) {
goto loser;
}
} else {
rv = PK11_Sign(privKey, &sigitem, &digder);
if (rv != SECSuccess) {
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);
PORT_Free(sigitem.data);
if (rv != SECSuccess)
goto loser;
SECITEM_FreeItem(&sigitem, PR_FALSE);
} else {
result->len = sigitem.len;
result->data = sigitem.data;
}
loser:
if (rv != SECSuccess) {
SECITEM_FreeItem(&sigitem, PR_FALSE);
}
SGN_DestroyDigestInfo(di);
if (arena != NULL) {
PORT_FreeArena(arena, PR_FALSE);
@ -229,18 +286,14 @@ loser:
/************************************************************************/
/*
** Sign a block of data returning in result a bunch of bytes that are the
** signature. Returns zero on success, an error code on failure.
*/
SECStatus
SEC_SignData(SECItem *res, const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid)
static SECStatus
sec_SignData(SECItem *res, const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid, SECItem *params)
{
SECStatus rv;
SGNContext *sgn;
sgn = SGN_NewContext(algid, pk);
sgn = sgn_NewContext(algid, params, pk);
if (sgn == NULL)
return SECFailure;
@ -260,6 +313,25 @@ loser:
return rv;
}
/*
** Sign a block of data returning in result a bunch of bytes that are the
** signature. Returns zero on success, an error code on failure.
*/
SECStatus
SEC_SignData(SECItem *res, const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECOidTag algid)
{
return sec_SignData(res, buf, len, pk, algid, NULL);
}
SECStatus
SEC_SignDataWithAlgorithmID(SECItem *res, const unsigned char *buf, int len,
SECKEYPrivateKey *pk, SECAlgorithmID *algid)
{
SECOidTag tag = SECOID_GetAlgorithmTag(algid);
return sec_SignData(res, buf, len, pk, tag, &algid->parameters);
}
/************************************************************************/
DERTemplate CERTSignedDataTemplate[] =
@ -294,10 +366,10 @@ const SEC_ASN1Template CERT_SignedDataTemplate[] =
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate)
SECStatus
SEC_DerSignData(PLArenaPool *arena, SECItem *result,
static SECStatus
sec_DerSignData(PLArenaPool *arena, SECItem *result,
const unsigned char *buf, int len, SECKEYPrivateKey *pk,
SECOidTag algID)
SECOidTag algID, SECItem *params)
{
SECItem it;
CERTSignedData sd;
@ -339,7 +411,7 @@ SEC_DerSignData(PLArenaPool *arena, SECItem *result,
}
/* Sign input buffer */
rv = SEC_SignData(&it, buf, len, pk, algID);
rv = sec_SignData(&it, buf, len, pk, algID, params);
if (rv)
goto loser;
@ -349,7 +421,7 @@ SEC_DerSignData(PLArenaPool *arena, SECItem *result,
sd.data.len = len;
sd.signature.data = it.data;
sd.signature.len = it.len << 3; /* convert to bit string */
rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0);
rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, params);
if (rv)
goto loser;
@ -362,6 +434,24 @@ loser:
return rv;
}
SECStatus
SEC_DerSignData(PLArenaPool *arena, SECItem *result,
const unsigned char *buf, int len, SECKEYPrivateKey *pk,
SECOidTag algID)
{
return sec_DerSignData(arena, result, buf, len, pk, algID, NULL);
}
SECStatus
SEC_DerSignDataWithAlgorithmID(PLArenaPool *arena, SECItem *result,
const unsigned char *buf, int len,
SECKEYPrivateKey *pk,
SECAlgorithmID *algID)
{
SECOidTag tag = SECOID_GetAlgorithmTag(algID);
return sec_DerSignData(arena, result, buf, len, pk, tag, &algID->parameters);
}
SECStatus
SGN_Digest(SECKEYPrivateKey *privKey,
SECOidTag algtag, SECItem *result, SECItem *digest)
@ -509,3 +599,243 @@ SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag)
}
return sigTag;
}
static SECItem *
sec_CreateRSAPSSParameters(PLArenaPool *arena,
SECItem *result,
SECOidTag hashAlgTag,
const SECItem *params,
const SECKEYPrivateKey *key)
{
SECKEYRSAPSSParams pssParams;
int modBytes, hashLength;
unsigned long saltLength;
PRBool defaultSHA1 = PR_FALSE;
SECStatus rv;
if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
PORT_Memset(&pssParams, 0, sizeof(pssParams));
if (params && params->data) {
/* The parameters field should either be empty or contain
* valid RSA-PSS parameters */
PORT_Assert(!(params->len == 2 &&
params->data[0] == SEC_ASN1_NULL &&
params->data[1] == 0));
rv = SEC_QuickDERDecodeItem(arena, &pssParams,
SECKEY_RSAPSSParamsTemplate,
params);
if (rv != SECSuccess) {
return NULL;
}
defaultSHA1 = PR_TRUE;
}
if (pssParams.trailerField.data) {
unsigned long trailerField;
rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.trailerField,
&trailerField);
if (rv != SECSuccess) {
return NULL;
}
if (trailerField != 1) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
}
modBytes = PK11_GetPrivateModulusLen((SECKEYPrivateKey *)key);
/* Determine the hash algorithm to use, based on hashAlgTag and
* pssParams.hashAlg; there are four cases */
if (hashAlgTag != SEC_OID_UNKNOWN) {
SECOidTag tag = SEC_OID_UNKNOWN;
if (pssParams.hashAlg) {
tag = SECOID_GetAlgorithmTag(pssParams.hashAlg);
} else if (defaultSHA1) {
tag = SEC_OID_SHA1;
}
if (tag != SEC_OID_UNKNOWN && tag != hashAlgTag) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
} else if (hashAlgTag == SEC_OID_UNKNOWN) {
if (pssParams.hashAlg) {
hashAlgTag = SECOID_GetAlgorithmTag(pssParams.hashAlg);
} else if (defaultSHA1) {
hashAlgTag = SEC_OID_SHA1;
} else {
/* Find a suitable hash algorithm based on the NIST recommendation */
if (modBytes <= 384) { /* 128, in NIST 800-57, Part 1 */
hashAlgTag = SEC_OID_SHA256;
} else if (modBytes <= 960) { /* 192, NIST 800-57, Part 1 */
hashAlgTag = SEC_OID_SHA384;
} else {
hashAlgTag = SEC_OID_SHA512;
}
}
}
if (hashAlgTag != SEC_OID_SHA1 && hashAlgTag != SEC_OID_SHA224 &&
hashAlgTag != SEC_OID_SHA256 && hashAlgTag != SEC_OID_SHA384 &&
hashAlgTag != SEC_OID_SHA512) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
/* Now that the hash algorithm is decided, check if it matches the
* existing parameters if any */
if (pssParams.maskAlg) {
SECAlgorithmID maskHashAlg;
if (SECOID_GetAlgorithmTag(pssParams.maskAlg) != SEC_OID_PKCS1_MGF1) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
if (pssParams.maskAlg->parameters.data == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
PORT_Memset(&maskHashAlg, 0, sizeof(maskHashAlg));
rv = SEC_QuickDERDecodeItem(arena, &maskHashAlg,
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
&pssParams.maskAlg->parameters);
if (rv != SECSuccess) {
return NULL;
}
/* Following the recommendation in RFC 4055, assume the hash
* algorithm identical to pssParam.hashAlg */
if (SECOID_GetAlgorithmTag(&maskHashAlg) != hashAlgTag) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
} else if (defaultSHA1) {
if (hashAlgTag != SEC_OID_SHA1) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
}
hashLength = HASH_ResultLenByOidTag(hashAlgTag);
if (pssParams.saltLength.data) {
rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.saltLength,
&saltLength);
if (rv != SECSuccess) {
return NULL;
}
/* The specified salt length is too long */
if (saltLength > modBytes - hashLength - 2) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
} else if (defaultSHA1) {
saltLength = 20;
}
/* Fill in the parameters */
if (pssParams.hashAlg) {
if (hashAlgTag == SEC_OID_SHA1) {
/* Omit hashAlg if the the algorithm is SHA-1 (default) */
pssParams.hashAlg = NULL;
}
} else {
if (hashAlgTag != SEC_OID_SHA1) {
pssParams.hashAlg = PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
if (!pssParams.hashAlg) {
return NULL;
}
rv = SECOID_SetAlgorithmID(arena, pssParams.hashAlg, hashAlgTag,
NULL);
if (rv != SECSuccess) {
return NULL;
}
}
}
if (pssParams.maskAlg) {
if (hashAlgTag == SEC_OID_SHA1) {
/* Omit maskAlg if the the algorithm is SHA-1 (default) */
pssParams.maskAlg = NULL;
}
} else {
if (hashAlgTag != SEC_OID_SHA1) {
SECItem *hashAlgItem;
PORT_Assert(pssParams.hashAlg != NULL);
hashAlgItem = SEC_ASN1EncodeItem(arena, NULL, pssParams.hashAlg,
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
if (!hashAlgItem) {
return NULL;
}
pssParams.maskAlg = PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
if (!pssParams.maskAlg) {
return NULL;
}
rv = SECOID_SetAlgorithmID(arena, pssParams.maskAlg,
SEC_OID_PKCS1_MGF1, hashAlgItem);
if (rv != SECSuccess) {
return NULL;
}
}
}
if (pssParams.saltLength.data) {
if (saltLength == 20) {
/* Omit the salt length if it is the default */
pssParams.saltLength.data = NULL;
}
} else {
/* Find a suitable length from the hash algorithm and modulus bits */
saltLength = PR_MIN(hashLength, modBytes - hashLength - 2);
if (saltLength != 20 &&
!SEC_ASN1EncodeInteger(arena, &pssParams.saltLength, saltLength)) {
return NULL;
}
}
if (pssParams.trailerField.data) {
/* Omit trailerField if the value is 1 (default) */
pssParams.trailerField.data = NULL;
}
return SEC_ASN1EncodeItem(arena, result,
&pssParams, SECKEY_RSAPSSParamsTemplate);
}
SECItem *
SEC_CreateSignatureAlgorithmParameters(PLArenaPool *arena,
SECItem *result,
SECOidTag signAlgTag,
SECOidTag hashAlgTag,
const SECItem *params,
const SECKEYPrivateKey *key)
{
switch (signAlgTag) {
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
return sec_CreateRSAPSSParameters(arena, result,
hashAlgTag, params, key);
default:
if (params == NULL)
return NULL;
if (result == NULL)
result = SECITEM_AllocItem(arena, NULL, 0);
if (SECITEM_CopyItem(arena, result, params) != SECSuccess)
return NULL;
return result;
}
}

View file

@ -136,6 +136,8 @@ struct VFYContextStr {
unsigned char dsasig[DSA_MAX_SIGNATURE_LEN];
/* the full ECDSA signature */
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];
} u;
unsigned int pkcs1RSADigestInfoLen;
/* the encoded DigestInfo from a RSA PKCS#1 signature */
@ -148,6 +150,7 @@ struct VFYContextStr {
* VFY_CreateContext call. If false, the
* signature must be provided with a
* VFY_EndWithSignature call. */
SECItem *params;
};
static SECStatus
@ -250,9 +253,38 @@ sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
*hashalg = SEC_OID_SHA1;
break;
case SEC_OID_PKCS1_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
*hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
break;
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
if (param && param->data) {
SECKEYRSAPSSParams pssParam;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
return SECFailure;
}
PORT_Memset(&pssParam, 0, sizeof pssParam);
rv = SEC_QuickDERDecodeItem(arena, &pssParam,
SECKEY_RSAPSSParamsTemplate,
param);
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
return rv;
}
if (pssParam.hashAlg) {
*hashalg = SECOID_GetAlgorithmTag(pssParam.hashAlg);
} else {
*hashalg = SEC_OID_SHA1; /* default, SHA-1 */
}
PORT_FreeArena(arena, PR_FALSE);
/* only accept hash algorithms */
if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
/* error set by HASH_GetHashTypeByOidTag */
return SECFailure;
}
} else {
*hashalg = SEC_OID_SHA1; /* default, SHA-1 */
}
break;
case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
@ -434,6 +466,20 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
cx->key,
sig, wincx);
break;
case rsaPssKey:
sigLen = SECKEY_SignatureLen(key);
if (sigLen == 0) {
/* error set by SECKEY_SignatureLen */
rv = SECFailure;
break;
}
if (sig->len != sigLen) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
rv = SECFailure;
break;
}
PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
break;
case dsaKey:
case ecKey:
sigLen = SECKEY_SignatureLen(key);
@ -496,6 +542,7 @@ VFYContext *
VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
{
VFYContext *cx;
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key,
SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
@ -503,7 +550,13 @@ VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
if (rv != SECSuccess) {
return NULL;
}
return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
if (sigAlgorithm->parameters.data) {
cx->params = SECITEM_DupItem(&sigAlgorithm->parameters);
}
return cx;
}
void
@ -520,6 +573,9 @@ VFY_DestroyContext(VFYContext *cx, PRBool freeit)
if (cx->pkcs1RSADigestInfo) {
PORT_Free(cx->pkcs1RSADigestInfo);
}
if (cx->params) {
SECITEM_FreeItem(cx->params, PR_TRUE);
}
if (freeit) {
PORT_ZFree(cx, sizeof(VFYContext));
}
@ -562,7 +618,7 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
{
unsigned char final[HASH_LENGTH_MAX];
unsigned part;
SECItem hash, dsasig; /* dsasig is also used for ECDSA */
SECItem hash, rsasig, dsasig; /* dsasig is also used for ECDSA */
SECStatus rv;
if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
@ -598,25 +654,70 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
return SECFailure;
}
break;
case rsaKey: {
SECItem digest;
digest.data = final;
digest.len = part;
if (sig) {
SECOidTag hashid;
PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN);
rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid,
&cx->pkcs1RSADigestInfo,
&cx->pkcs1RSADigestInfoLen,
cx->key,
sig, cx->wincx);
PORT_Assert(cx->hashAlg == hashid);
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) };
SECKEYRSAPSSParams params;
PLArenaPool *arena;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
return SECFailure;
}
PORT_Memset(&params, 0, sizeof(params));
rv = SEC_QuickDERDecodeItem(arena, &params,
SECKEY_RSAPSSParamsTemplate,
cx->params);
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
return SECFailure;
}
rv = sec_RSAPSSParamsToMechanism(&mech, &params);
PORT_FreeArena(arena, PR_FALSE);
if (rv != SECSuccess) {
return SECFailure;
}
rsasig.data = cx->u.buffer;
rsasig.len = SECKEY_SignatureLen(cx->key);
if (rsasig.len == 0) {
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) {
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);
rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid,
&cx->pkcs1RSADigestInfo,
&cx->pkcs1RSADigestInfoLen,
cx->key,
sig, cx->wincx);
PORT_Assert(cx->hashAlg == hashid);
if (rv != SECSuccess) {
return SECFailure;
}
}
return verifyPKCS1DigestInfo(cx, &digest);
}
return verifyPKCS1DigestInfo(cx, &digest);
}
break;
default:
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure; /* shouldn't happen */
@ -722,7 +823,7 @@ VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
static SECStatus
vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx)
const SECItem *params, SECOidTag *hash, void *wincx)
{
SECStatus rv;
VFYContext *cx;
@ -730,6 +831,9 @@ vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
if (cx == NULL)
return SECFailure;
if (params) {
cx->params = SECITEM_DupItem(params);
}
rv = VFY_Begin(cx);
if (rv == SECSuccess) {
@ -748,7 +852,7 @@ 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, hash, wincx);
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, hash, wincx);
}
SECStatus
@ -760,7 +864,7 @@ VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
if (rv != SECSuccess) {
return rv;
}
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx);
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, NULL, wincx);
}
SECStatus
@ -777,5 +881,6 @@ VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
if (rv != SECSuccess) {
return rv;
}
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg,
&sigAlgorithm->parameters, hash, wincx);
}

View file

@ -426,6 +426,9 @@ ugly_split(HTAB *hashp, uint32 obucket, BUFHEAD *old_bufp,
last_bfp = NULL;
scopyto = (uint16)copyto; /* ANSI */
if (ino[0] < 1) {
return DATABASE_CORRUPTED_ERROR;
}
n = ino[0] - 1;
while (n < ino[0]) {
@ -463,7 +466,13 @@ ugly_split(HTAB *hashp, uint32 obucket, BUFHEAD *old_bufp,
* Fix up the old page -- the extra 2 are the fields
* which contained the overflow information.
*/
if (ino[0] < (moved + 2)) {
return DATABASE_CORRUPTED_ERROR;
}
ino[0] -= (moved + 2);
if (scopyto < sizeof(uint16) * (ino[0] + 3)) {
return DATABASE_CORRUPTED_ERROR;
}
FREESPACE(ino) =
scopyto - sizeof(uint16) * (ino[0] + 3);
OFFSET(ino) = scopyto;
@ -486,8 +495,14 @@ ugly_split(HTAB *hashp, uint32 obucket, BUFHEAD *old_bufp,
for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
cino = (char *)ino;
key.data = (uint8 *)cino + ino[n];
if (off < ino[n]) {
return DATABASE_CORRUPTED_ERROR;
}
key.size = off - ino[n];
val.data = (uint8 *)cino + ino[n + 1];
if (ino[n] < ino[n + 1]) {
return DATABASE_CORRUPTED_ERROR;
}
val.size = ino[n] - ino[n + 1];
off = ino[n + 1];

View file

@ -704,8 +704,7 @@ hash_put(
return (DBM_ERROR);
}
rv = hash_access(hashp, flag == R_NOOVERWRITE ? HASH_PUTNEW
: HASH_PUT,
rv = hash_access(hashp, flag == R_NOOVERWRITE ? HASH_PUTNEW : HASH_PUT,
(DBT *)key, (DBT *)data);
if (rv == DATABASE_CORRUPTED_ERROR) {

View file

@ -32,15 +32,21 @@ nssCryptokiObject_Create(
/* a failure here indicates a device error */
return (nssCryptokiObject *)NULL;
}
if (cert_template[0].ulValueLen == 0) {
nss_ZFreeIf(cert_template[1].pValue);
return (nssCryptokiObject *)NULL;
}
object = nss_ZNEW(NULL, nssCryptokiObject);
if (!object) {
nss_ZFreeIf(cert_template[0].pValue);
nss_ZFreeIf(cert_template[1].pValue);
return (nssCryptokiObject *)NULL;
}
object->handle = h;
object->token = nssToken_AddRef(t);
isTokenObject = (CK_BBOOL *)cert_template[0].pValue;
object->isTokenObject = *isTokenObject;
nss_ZFreeIf(isTokenObject);
nss_ZFreeIf(cert_template[0].pValue);
NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label);
return object;
}

View file

@ -110,7 +110,9 @@ endif
# NSS_X86_OR_X64 means the target is either x86 or x64
ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
DEFINES += -DNSS_X86_OR_X64
CFLAGS += -mpclmul -maes
EXTRA_SRCS += gcm-x86.c aes-x86.c
$(OBJDIR)/gcm-x86.o: CFLAGS += -mpclmul -maes
$(OBJDIR)/aes-x86.o: CFLAGS += -mpclmul -maes
ifneq (,$(USE_64)$(USE_X32))
DEFINES += -DNSS_X64
else
@ -490,8 +492,6 @@ else
endif # Solaris for non-sparc family CPUs
endif # target == SunO
# poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
# in GCC 4.6.0.
ifdef USE_64
ifdef CC_IS_CLANG
HAVE_INT128_SUPPORT = 1
@ -508,38 +508,41 @@ ifdef USE_64
endif
endif
ifndef HAVE_INT128_SUPPORT
DEFINES += -DKRML_NOUINT128
endif
ifndef NSS_DISABLE_CHACHAPOLY
ifeq ($(CPU_ARCH),x86_64)
ifdef HAVE_INT128_SUPPORT
EXTRA_SRCS += poly1305-donna-x64-sse2-incremental-source.c
EXTRA_SRCS += Hacl_Poly1305_64.c
else
EXTRA_SRCS += poly1305.c
endif
ifneq (1,$(CC_IS_GCC))
EXTRA_SRCS += chacha20.c
VERIFIED_SRCS += Hacl_Chacha20.c
else
EXTRA_SRCS += chacha20_vec.c
endif
else
EXTRA_SRCS += poly1305.c
EXTRA_SRCS += chacha20.c
VERIFIED_SRCS += Hacl_Chacha20.c
endif # x86_64
endif # NSS_DISABLE_CHACHAPOLY
ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
ifeq (,$(filter-out i386 x386 x86 x86_64 aarch64,$(CPU_ARCH)))
# All intel architectures get the 64 bit version
# With custom uint128 if necessary (faster than generic 32 bit version).
ECL_SRCS += curve25519_64.c
VERIFIED_SRCS += Hacl_Curve25519.c FStar.c
else
# All non intel architectures get the generic 32 bit implementation (slow!)
ECL_SRCS += curve25519_32.c
endif
ifndef HAVE_INT128_SUPPORT
ECL_SRCS += uint128.c
endif
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
@ -563,12 +566,12 @@ rijndael_tables:
$(DEFINES) $(INCLUDES) $(OBJDIR)/libfreebl.a
$(OBJDIR)/make_rijndael_tab
vpath %.h mpi ecl
vpath %.c mpi ecl
vpath %.h mpi ecl verified
vpath %.c mpi ecl verified
vpath %.S mpi ecl
vpath %.s mpi ecl
vpath %.asm mpi ecl
INCLUDES += -Impi -Iecl
INCLUDES += -Impi -Iecl -Iverified
DEFINES += -DMP_API_COMPATIBLE
@ -587,8 +590,6 @@ ECL_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_USERS:.c=$(OBJ_SUFFIX)))
$(ECL_OBJS): $(ECL_HDRS)
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c

View file

@ -0,0 +1,157 @@
/* 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 "rijndael.h"
#include "secerr.h"
#include <wmmintrin.h> /* aes-ni */
#define EXPAND_KEY128(k, rcon, res) \
tmp_key = _mm_aeskeygenassist_si128(k, rcon); \
tmp_key = _mm_shuffle_epi32(tmp_key, 0xFF); \
tmp = _mm_xor_si128(k, _mm_slli_si128(k, 4)); \
tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
res = _mm_xor_si128(tmp, tmp_key)
static void
native_key_expansion128(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
EXPAND_KEY128(keySchedule[0], 0x01, keySchedule[1]);
EXPAND_KEY128(keySchedule[1], 0x02, keySchedule[2]);
EXPAND_KEY128(keySchedule[2], 0x04, keySchedule[3]);
EXPAND_KEY128(keySchedule[3], 0x08, keySchedule[4]);
EXPAND_KEY128(keySchedule[4], 0x10, keySchedule[5]);
EXPAND_KEY128(keySchedule[5], 0x20, keySchedule[6]);
EXPAND_KEY128(keySchedule[6], 0x40, keySchedule[7]);
EXPAND_KEY128(keySchedule[7], 0x80, keySchedule[8]);
EXPAND_KEY128(keySchedule[8], 0x1B, keySchedule[9]);
EXPAND_KEY128(keySchedule[9], 0x36, keySchedule[10]);
}
#define EXPAND_KEY192_PART1(res, k0, kt, rcon) \
tmp2 = _mm_slli_si128(k0, 4); \
tmp1 = _mm_xor_si128(k0, tmp2); \
tmp2 = _mm_slli_si128(tmp2, 4); \
tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
tmp2 = _mm_aeskeygenassist_si128(kt, rcon); \
res = _mm_xor_si128(tmp1, _mm_shuffle_epi32(tmp2, 0x55))
#define EXPAND_KEY192_PART2(res, k1, k2) \
tmp2 = _mm_xor_si128(k1, _mm_slli_si128(k1, 4)); \
res = _mm_xor_si128(tmp2, _mm_shuffle_epi32(k2, 0xFF))
#define EXPAND_KEY192(k0, res1, res2, res3, carry, rcon1, rcon2) \
EXPAND_KEY192_PART1(tmp3, k0, res1, rcon1); \
EXPAND_KEY192_PART2(carry, res1, tmp3); \
res1 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(res1), \
_mm_castsi128_pd(tmp3), 0)); \
res2 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(tmp3), \
_mm_castsi128_pd(carry), 1)); \
EXPAND_KEY192_PART1(res3, tmp3, carry, rcon2)
static void
native_key_expansion192(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
pre_align __m128i tmp3 post_align;
pre_align __m128i carry post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
EXPAND_KEY192(keySchedule[0], keySchedule[1], keySchedule[2],
keySchedule[3], carry, 0x1, 0x2);
EXPAND_KEY192_PART2(keySchedule[4], carry, keySchedule[3]);
EXPAND_KEY192(keySchedule[3], keySchedule[4], keySchedule[5],
keySchedule[6], carry, 0x4, 0x8);
EXPAND_KEY192_PART2(keySchedule[7], carry, keySchedule[6]);
EXPAND_KEY192(keySchedule[6], keySchedule[7], keySchedule[8],
keySchedule[9], carry, 0x10, 0x20);
EXPAND_KEY192_PART2(keySchedule[10], carry, keySchedule[9]);
EXPAND_KEY192(keySchedule[9], keySchedule[10], keySchedule[11],
keySchedule[12], carry, 0x40, 0x80);
}
#define EXPAND_KEY256_PART(res, rconx, k1x, k2x, X) \
tmp_key = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(k2x, rconx), X); \
tmp2 = _mm_slli_si128(k1x, 4); \
tmp1 = _mm_xor_si128(k1x, tmp2); \
tmp2 = _mm_slli_si128(tmp2, 4); \
tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
res = _mm_xor_si128(tmp1, tmp_key);
#define EXPAND_KEY256(res1, res2, k1, k2, rcon) \
EXPAND_KEY256_PART(res1, rcon, k1, k2, 0xFF); \
EXPAND_KEY256_PART(res2, 0x00, k2, res1, 0xAA)
static void
native_key_expansion256(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
EXPAND_KEY256(keySchedule[2], keySchedule[3], keySchedule[0],
keySchedule[1], 0x01);
EXPAND_KEY256(keySchedule[4], keySchedule[5], keySchedule[2],
keySchedule[3], 0x02);
EXPAND_KEY256(keySchedule[6], keySchedule[7], keySchedule[4],
keySchedule[5], 0x04);
EXPAND_KEY256(keySchedule[8], keySchedule[9], keySchedule[6],
keySchedule[7], 0x08);
EXPAND_KEY256(keySchedule[10], keySchedule[11], keySchedule[8],
keySchedule[9], 0x10);
EXPAND_KEY256(keySchedule[12], keySchedule[13], keySchedule[10],
keySchedule[11], 0x20);
EXPAND_KEY256_PART(keySchedule[14], 0x40, keySchedule[12],
keySchedule[13], 0xFF);
}
/*
* AES key expansion using aes-ni instructions.
*/
void
rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
unsigned int Nk)
{
switch (Nk) {
case 4:
native_key_expansion128(cx, key);
return;
case 6:
native_key_expansion192(cx, key);
return;
case 8:
native_key_expansion256(cx, key);
return;
default:
/* This shouldn't happen (checked by the caller). */
return;
}
}
void
rijndael_native_encryptBlock(AESContext *cx,
unsigned char *output,
const unsigned char *input)
{
int i;
pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
m = _mm_xor_si128(m, cx->keySchedule[0]);
for (i = 1; i < cx->Nr; ++i) {
m = _mm_aesenc_si128(m, cx->keySchedule[i]);
}
m = _mm_aesenclast_si128(m, cx->keySchedule[cx->Nr]);
_mm_storeu_si128((__m128i *)output, m);
}

View file

@ -0,0 +1,430 @@
/*
* blake2b.c - definitions for the blake2b hash function
*
* 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 "secerr.h"
#include "blapi.h"
#include "blake2b.h"
#include "crypto_primitives.h"
/**
* This contains the BLAKE2b initialization vectors.
*/
static const uint64_t iv[8] = {
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
/**
* This contains the table of permutations for blake2b compression function.
*/
static const uint8_t sigma[12][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
};
/**
* This function increments the blake2b ctx counter.
*/
void
blake2b_IncrementCounter(BLAKE2BContext* ctx, const uint64_t inc)
{
ctx->t[0] += inc;
ctx->t[1] += ctx->t[0] < inc;
}
/**
* This macro implements the blake2b mixing function which mixes two 8-byte
* words from the message into the hash.
*/
#define G(a, b, c, d, x, y) \
a += b + x; \
d = ROTR64(d ^ a, 32); \
c += d; \
b = ROTR64(b ^ c, 24); \
a += b + y; \
d = ROTR64(d ^ a, 16); \
c += d; \
b = ROTR64(b ^ c, 63)
#define ROUND(i) \
G(v[0], v[4], v[8], v[12], m[sigma[i][0]], m[sigma[i][1]]); \
G(v[1], v[5], v[9], v[13], m[sigma[i][2]], m[sigma[i][3]]); \
G(v[2], v[6], v[10], v[14], m[sigma[i][4]], m[sigma[i][5]]); \
G(v[3], v[7], v[11], v[15], m[sigma[i][6]], m[sigma[i][7]]); \
G(v[0], v[5], v[10], v[15], m[sigma[i][8]], m[sigma[i][9]]); \
G(v[1], v[6], v[11], v[12], m[sigma[i][10]], m[sigma[i][11]]); \
G(v[2], v[7], v[8], v[13], m[sigma[i][12]], m[sigma[i][13]]); \
G(v[3], v[4], v[9], v[14], m[sigma[i][14]], m[sigma[i][15]])
/**
* The blake2b compression function which takes a full 128-byte chunk of the
* input message and mixes it into the ongoing ctx array, i.e., permute the
* ctx while xoring in the block of data.
*/
void
blake2b_Compress(BLAKE2BContext* ctx, const uint8_t* block)
{
size_t i;
uint64_t v[16], m[16];
PORT_Memcpy(m, block, BLAKE2B_BLOCK_LENGTH);
#if !defined(IS_LITTLE_ENDIAN)
for (i = 0; i < 16; ++i) {
m[i] = FREEBL_HTONLL(m[i]);
}
#endif
PORT_Memcpy(v, ctx->h, 8 * 8);
PORT_Memcpy(v + 8, iv, 8 * 8);
v[12] ^= ctx->t[0];
v[13] ^= ctx->t[1];
v[14] ^= ctx->f;
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
ROUND(10);
ROUND(11);
for (i = 0; i < 8; i++) {
ctx->h[i] ^= v[i] ^ v[i + 8];
}
}
/**
* This function can be used for both keyed and unkeyed version.
*/
BLAKE2BContext*
BLAKE2B_NewContext()
{
return PORT_ZNew(BLAKE2BContext);
}
/**
* Zero and free the context and can be used for both keyed and unkeyed version.
*/
void
BLAKE2B_DestroyContext(BLAKE2BContext* ctx, PRBool freeit)
{
PORT_Memset(ctx, 0, sizeof(*ctx));
if (freeit) {
PORT_Free(ctx);
}
}
/**
* This function initializes blake2b ctx and can be used for both keyed and
* unkeyed version. It also checks ctx and sets error states.
*/
static SECStatus
blake2b_Begin(BLAKE2BContext* ctx, uint8_t outlen, const uint8_t* key,
size_t keylen)
{
PORT_Assert(ctx != NULL);
if (!ctx) {
goto failure;
}
if (outlen == 0 || outlen > BLAKE2B512_LENGTH) {
goto failure;
}
if (key && keylen > BLAKE2B_KEY_SIZE) {
goto failure;
}
/* Note: key can be null if it's unkeyed. */
if ((key == NULL && keylen > 0) || keylen > BLAKE2B_KEY_SIZE ||
(key != NULL && keylen == 0)) {
goto failure;
}
/* Mix key size(keylen) and desired hash length(outlen) into h0 */
uint64_t param = outlen ^ (keylen << 8) ^ (1 << 16) ^ (1 << 24);
PORT_Memcpy(ctx->h, iv, 8 * 8);
ctx->h[0] ^= param;
ctx->outlen = outlen;
/* This updates the context for only the keyed version */
if (keylen > 0 && keylen <= BLAKE2B_KEY_SIZE && key) {
uint8_t block[BLAKE2B_BLOCK_LENGTH] = { 0 };
PORT_Memcpy(block, key, keylen);
BLAKE2B_Update(ctx, block, BLAKE2B_BLOCK_LENGTH);
PORT_Memset(block, 0, BLAKE2B_BLOCK_LENGTH);
}
return SECSuccess;
failure:
PORT_Memset(&ctx, 0, sizeof(ctx));
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
SECStatus
BLAKE2B_Begin(BLAKE2BContext* ctx)
{
return blake2b_Begin(ctx, BLAKE2B512_LENGTH, NULL, 0);
}
SECStatus
BLAKE2B_MAC_Begin(BLAKE2BContext* ctx, const PRUint8* key, const size_t keylen)
{
PORT_Assert(key != NULL);
if (!key) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
return blake2b_Begin(ctx, BLAKE2B512_LENGTH, (const uint8_t*)key, keylen);
}
static void
blake2b_IncrementCompress(BLAKE2BContext* ctx, size_t blockLength,
const unsigned char* input)
{
blake2b_IncrementCounter(ctx, blockLength);
blake2b_Compress(ctx, input);
}
/**
* This function updates blake2b ctx and can be used for both keyed and unkeyed
* version.
*/
SECStatus
BLAKE2B_Update(BLAKE2BContext* ctx, const unsigned char* in,
unsigned int inlen)
{
size_t left = ctx->buflen;
size_t fill = BLAKE2B_BLOCK_LENGTH - left;
/* Nothing to do if there's nothing. */
if (inlen == 0) {
return SECSuccess;
}
PORT_Assert(ctx != NULL);
PORT_Assert(in != NULL);
PORT_Assert(left <= BLAKE2B_BLOCK_LENGTH);
if (!ctx || !in) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Is this a reused context? */
if (ctx->f) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (inlen > fill) {
if (ctx->buflen) {
/* There's some remaining data in ctx->buf that we have to prepend
* to in. */
PORT_Memcpy(ctx->buf + left, in, fill);
ctx->buflen = 0;
blake2b_IncrementCompress(ctx, BLAKE2B_BLOCK_LENGTH, ctx->buf);
in += fill;
inlen -= fill;
}
while (inlen > BLAKE2B_BLOCK_LENGTH) {
blake2b_IncrementCompress(ctx, BLAKE2B_BLOCK_LENGTH, in);
in += BLAKE2B_BLOCK_LENGTH;
inlen -= BLAKE2B_BLOCK_LENGTH;
}
}
/* Store the remaining data from in in ctx->buf to process later.
* Note that ctx->buflen can be BLAKE2B_BLOCK_LENGTH. We can't process that
* here because we have to update ctx->f before compressing the last block.
*/
PORT_Assert(inlen <= BLAKE2B_BLOCK_LENGTH);
PORT_Memcpy(ctx->buf + ctx->buflen, in, inlen);
ctx->buflen += inlen;
return SECSuccess;
}
/**
* This function finalizes ctx, pads final block and stores hash.
* It can be used for both keyed and unkeyed version.
*/
SECStatus
BLAKE2B_End(BLAKE2BContext* ctx, unsigned char* out,
unsigned int* digestLen, size_t maxDigestLen)
{
size_t i;
unsigned int outlen = PR_MIN(BLAKE2B512_LENGTH, maxDigestLen);
/* Argument checks */
if (!ctx || !out) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Sanity check against outlen in context. */
if (ctx->outlen < outlen) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Is this a reused context? */
if (ctx->f != 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Process the remaining data from ctx->buf (padded with 0). */
blake2b_IncrementCounter(ctx, ctx->buflen);
/* BLAKE2B_BLOCK_LENGTH - ctx->buflen can be 0. */
PORT_Memset(ctx->buf + ctx->buflen, 0, BLAKE2B_BLOCK_LENGTH - ctx->buflen);
ctx->f = UINT64_MAX;
blake2b_Compress(ctx, ctx->buf);
/* Write out the blake2b context(ctx). */
for (i = 0; i < outlen; ++i) {
out[i] = ctx->h[i / 8] >> ((i % 8) * 8);
}
if (digestLen) {
*digestLen = outlen;
}
return SECSuccess;
}
SECStatus
blake2b_HashBuf(uint8_t* output, const uint8_t* input, uint8_t outlen,
size_t inlen, const uint8_t* key, size_t keylen)
{
SECStatus rv = SECFailure;
BLAKE2BContext ctx = { { 0 } };
if (inlen != 0) {
PORT_Assert(input != NULL);
if (input == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto done;
}
}
PORT_Assert(output != NULL);
if (output == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto done;
}
if (blake2b_Begin(&ctx, outlen, key, keylen) != SECSuccess) {
goto done;
}
if (BLAKE2B_Update(&ctx, input, inlen) != SECSuccess) {
goto done;
}
if (BLAKE2B_End(&ctx, output, NULL, outlen) != SECSuccess) {
goto done;
}
rv = SECSuccess;
done:
PORT_Memset(&ctx, 0, sizeof ctx);
return rv;
}
SECStatus
BLAKE2B_Hash(unsigned char* dest, const char* src)
{
return blake2b_HashBuf(dest, (const unsigned char*)src, BLAKE2B512_LENGTH,
PORT_Strlen(src), NULL, 0);
}
SECStatus
BLAKE2B_HashBuf(unsigned char* output, const unsigned char* input, PRUint32 inlen)
{
return blake2b_HashBuf(output, input, BLAKE2B512_LENGTH, inlen, NULL, 0);
}
SECStatus
BLAKE2B_MAC_HashBuf(unsigned char* output, const unsigned char* input,
unsigned int inlen, const unsigned char* key,
unsigned int keylen)
{
PORT_Assert(key != NULL);
if (!key && keylen <= BLAKE2B_KEY_SIZE) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
return blake2b_HashBuf(output, input, BLAKE2B512_LENGTH, inlen, key, keylen);
}
unsigned int
BLAKE2B_FlattenSize(BLAKE2BContext* ctx)
{
return sizeof(BLAKE2BContext);
}
SECStatus
BLAKE2B_Flatten(BLAKE2BContext* ctx, unsigned char* space)
{
PORT_Assert(space != NULL);
if (!space) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
PORT_Memcpy(space, ctx, sizeof(BLAKE2BContext));
return SECSuccess;
}
BLAKE2BContext*
BLAKE2B_Resurrect(unsigned char* space, void* arg)
{
PORT_Assert(space != NULL);
if (!space) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
BLAKE2BContext* ctx = BLAKE2B_NewContext();
if (ctx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
PORT_Memcpy(ctx, space, sizeof(BLAKE2BContext));
return ctx;
}
void
BLAKE2B_Clone(BLAKE2BContext* dest, BLAKE2BContext* src)
{
PORT_Assert(dest != NULL);
PORT_Assert(src != NULL);
if (!dest || !src) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return;
}
PORT_Memcpy(dest, src, sizeof(BLAKE2BContext));
}

View file

@ -0,0 +1,23 @@
/*
* blake2b.h - header file for blake2b hash function
*
* 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 BLAKE_H
#define BLAKE_H
#include <stddef.h>
#include <stdint.h>
struct Blake2bContextStr {
uint64_t h[8]; /* chained state */
uint64_t t[2]; /* total number of bytes */
uint64_t f; /* last block flag */
uint8_t buf[BLAKE2B_BLOCK_LENGTH]; /* input buffer */
size_t buflen; /* size of remaining bytes in buf */
size_t outlen; /* digest size */
};
#endif /* BLAKE_H */

View file

@ -1400,6 +1400,84 @@ extern SECStatus
TLS_P_hash(HASH_HashType hashAlg, const SECItem *secret, const char *label,
SECItem *seed, SECItem *result, PRBool isFIPS);
/******************************************/
/*
** Implements the Blake2b hash function.
*/
/*
** Hash a null terminated string "src" into "dest" using Blake2b
*/
extern SECStatus BLAKE2B_Hash(unsigned char *dest, const char *src);
/*
** Hash a non-null terminated string "src" into "dest" using Blake2b
*/
extern SECStatus BLAKE2B_HashBuf(unsigned char *output,
const unsigned char *input, PRUint32 inlen);
extern SECStatus BLAKE2B_MAC_HashBuf(unsigned char *output,
const unsigned char *input,
unsigned int inlen,
const unsigned char *key,
unsigned int keylen);
/*
** Create a new Blake2b context
*/
extern BLAKE2BContext *BLAKE2B_NewContext();
/*
** Destroy a Blake2b secure hash context.
** "ctx" the context
** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
extern void BLAKE2B_DestroyContext(BLAKE2BContext *ctx, PRBool freeit);
/*
** Reset a Blake2b context, preparing it for a fresh round of hashing
*/
extern SECStatus BLAKE2B_Begin(BLAKE2BContext *ctx);
extern SECStatus BLAKE2B_MAC_Begin(BLAKE2BContext *ctx, const PRUint8 *key,
const size_t keylen);
/*
** Update the Blake hash function with more data.
*/
extern SECStatus BLAKE2B_Update(BLAKE2BContext *ctx, const unsigned char *in,
unsigned int inlen);
/*
** Finish the Blake hash function. Produce the digested results in "digest"
*/
extern SECStatus BLAKE2B_End(BLAKE2BContext *ctx, unsigned char *out,
unsigned int *digestLen, size_t maxDigestLen);
/*
* Return the size of a buffer needed to flatten the Blake2b Context into
* "ctx" the context
* returns size;
*/
extern unsigned int BLAKE2B_FlattenSize(BLAKE2BContext *ctx);
/*
* Flatten the Blake2b Context into a buffer:
* "ctx" the context
* "space" the buffer to flatten to
* returns status;
*/
extern SECStatus BLAKE2B_Flatten(BLAKE2BContext *ctx, unsigned char *space);
/*
* Resurrect a flattened context into a Blake2b Context
* "space" the buffer of the flattend buffer
* "arg" ptr to void used by cryptographic resurrect
* returns resurected context
*/
extern BLAKE2BContext *BLAKE2B_Resurrect(unsigned char *space, void *arg);
extern void BLAKE2B_Clone(BLAKE2BContext *dest, BLAKE2BContext *src);
/******************************************/
/*
** Pseudo Random Number Generation. FIPS compliance desirable.

View file

@ -22,8 +22,10 @@ typedef void (*freeblDestroyFunc)(void *cx, PRBool freeit);
SEC_BEGIN_PROTOS
#ifndef NSS_FIPS_DISABLED
SECStatus BL_FIPSEntryOK(PRBool freeblOnly);
PRBool BL_POSTRan(PRBool freeblOnly);
#endif
#if defined(XP_UNIX) && !defined(NO_FORK_CHECK)

View file

@ -91,25 +91,27 @@ typedef int __BLAPI_DEPRECATED __attribute__((deprecated));
/*
* Number of bytes each hash algorithm produces
*/
#define MD2_LENGTH 16 /* Bytes */
#define MD5_LENGTH 16 /* Bytes */
#define SHA1_LENGTH 20 /* Bytes */
#define SHA256_LENGTH 32 /* bytes */
#define SHA384_LENGTH 48 /* bytes */
#define SHA512_LENGTH 64 /* bytes */
#define MD2_LENGTH 16 /* Bytes */
#define MD5_LENGTH 16 /* Bytes */
#define SHA1_LENGTH 20 /* Bytes */
#define SHA256_LENGTH 32 /* bytes */
#define SHA384_LENGTH 48 /* bytes */
#define SHA512_LENGTH 64 /* bytes */
#define BLAKE2B512_LENGTH 64 /* Bytes */
#define HASH_LENGTH_MAX SHA512_LENGTH
/*
* Input block size for each hash algorithm.
*/
#define MD2_BLOCK_LENGTH 64 /* bytes */
#define MD5_BLOCK_LENGTH 64 /* bytes */
#define SHA1_BLOCK_LENGTH 64 /* bytes */
#define SHA224_BLOCK_LENGTH 64 /* bytes */
#define SHA256_BLOCK_LENGTH 64 /* bytes */
#define SHA384_BLOCK_LENGTH 128 /* bytes */
#define SHA512_BLOCK_LENGTH 128 /* bytes */
#define MD2_BLOCK_LENGTH 64 /* bytes */
#define MD5_BLOCK_LENGTH 64 /* bytes */
#define SHA1_BLOCK_LENGTH 64 /* bytes */
#define SHA224_BLOCK_LENGTH 64 /* bytes */
#define SHA256_BLOCK_LENGTH 64 /* bytes */
#define SHA384_BLOCK_LENGTH 128 /* bytes */
#define SHA512_BLOCK_LENGTH 128 /* bytes */
#define BLAKE2B_BLOCK_LENGTH 128 /* Bytes */
#define HASH_BLOCK_LENGTH_MAX SHA512_BLOCK_LENGTH
#define AES_KEY_WRAP_IV_BYTES 8
@ -127,6 +129,8 @@ typedef int __BLAPI_DEPRECATED __attribute__((deprecated));
#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
#define BLAKE2B_KEY_SIZE 64
/*
* These values come from the initial key size limits from the PKCS #11
* module. They may be arbitrarily adjusted to any value freebl supports.
@ -213,6 +217,7 @@ struct SHA512ContextStr;
struct AESKeyWrapContextStr;
struct SEEDContextStr;
struct ChaCha20Poly1305ContextStr;
struct Blake2bContextStr;
typedef struct DESContextStr DESContext;
typedef struct RC2ContextStr RC2Context;
@ -232,6 +237,7 @@ typedef struct SHA512ContextStr SHA384Context;
typedef struct AESKeyWrapContextStr AESKeyWrapContext;
typedef struct SEEDContextStr SEEDContext;
typedef struct ChaCha20Poly1305ContextStr ChaCha20Poly1305Context;
typedef struct Blake2bContextStr BLAKE2BContext;
/***************************************************************************
** RSA Public and Private Key structures

View file

@ -7,113 +7,13 @@
#include <string.h>
#include <stdio.h>
#include "prtypes.h"
#include "secport.h"
#include "chacha20.h"
#if defined(_MSC_VER)
#pragma intrinsic(_lrotl)
#define ROTL32(x, n) _lrotl(x, n)
#else
#define ROTL32(x, n) ((x << n) | (x >> ((8 * sizeof x) - n)))
#endif
#define ROTATE(v, c) ROTL32((v), (c))
#define U32TO8_LITTLE(p, v) \
{ \
(p)[0] = ((v)) & 0xff; \
(p)[1] = ((v) >> 8) & 0xff; \
(p)[2] = ((v) >> 16) & 0xff; \
(p)[3] = ((v) >> 24) & 0xff; \
}
#define U8TO32_LITTLE(p) \
(((PRUint32)((p)[0])) | ((PRUint32)((p)[1]) << 8) | \
((PRUint32)((p)[2]) << 16) | ((PRUint32)((p)[3]) << 24))
#define QUARTERROUND(x, a, b, c, d) \
x[a] = x[a] + x[b]; \
x[d] = ROTATE(x[d] ^ x[a], 16); \
x[c] = x[c] + x[d]; \
x[b] = ROTATE(x[b] ^ x[c], 12); \
x[a] = x[a] + x[b]; \
x[d] = ROTATE(x[d] ^ x[a], 8); \
x[c] = x[c] + x[d]; \
x[b] = ROTATE(x[b] ^ x[c], 7);
static void
ChaChaCore(unsigned char output[64], const PRUint32 input[16], int num_rounds)
{
PRUint32 x[16];
int i;
PORT_Memcpy(x, input, sizeof(PRUint32) * 16);
for (i = num_rounds; i > 0; i -= 2) {
QUARTERROUND(x, 0, 4, 8, 12)
QUARTERROUND(x, 1, 5, 9, 13)
QUARTERROUND(x, 2, 6, 10, 14)
QUARTERROUND(x, 3, 7, 11, 15)
QUARTERROUND(x, 0, 5, 10, 15)
QUARTERROUND(x, 1, 6, 11, 12)
QUARTERROUND(x, 2, 7, 8, 13)
QUARTERROUND(x, 3, 4, 9, 14)
}
for (i = 0; i < 16; ++i) {
x[i] = x[i] + input[i];
}
for (i = 0; i < 16; ++i) {
U32TO8_LITTLE(output + 4 * i, x[i]);
}
}
static const unsigned char sigma[16] = "expand 32-byte k";
#include "verified/Hacl_Chacha20.h"
void
ChaCha20XOR(unsigned char *out, const unsigned char *in, unsigned int inLen,
const unsigned char key[32], const unsigned char nonce[12],
uint32_t counter)
{
unsigned char block[64];
PRUint32 input[16];
unsigned int i;
input[4] = U8TO32_LITTLE(key + 0);
input[5] = U8TO32_LITTLE(key + 4);
input[6] = U8TO32_LITTLE(key + 8);
input[7] = U8TO32_LITTLE(key + 12);
input[8] = U8TO32_LITTLE(key + 16);
input[9] = U8TO32_LITTLE(key + 20);
input[10] = U8TO32_LITTLE(key + 24);
input[11] = U8TO32_LITTLE(key + 28);
input[0] = U8TO32_LITTLE(sigma + 0);
input[1] = U8TO32_LITTLE(sigma + 4);
input[2] = U8TO32_LITTLE(sigma + 8);
input[3] = U8TO32_LITTLE(sigma + 12);
input[12] = counter;
input[13] = U8TO32_LITTLE(nonce + 0);
input[14] = U8TO32_LITTLE(nonce + 4);
input[15] = U8TO32_LITTLE(nonce + 8);
while (inLen >= 64) {
ChaChaCore(block, input, 20);
for (i = 0; i < 64; i++) {
out[i] = in[i] ^ block[i];
}
input[12]++;
inLen -= 64;
in += 64;
out += 64;
}
if (inLen > 0) {
ChaChaCore(block, input, 20);
for (i = 0; i < inLen; i++) {
out[i] = in[i] ^ block[i];
}
}
Hacl_Chacha20_chacha20(out, (uint8_t *)in, inLen, (uint8_t *)key, (uint8_t *)nonce, counter);
}

View file

@ -14,7 +14,11 @@
#include "blapit.h"
#ifndef NSS_DISABLE_CHACHAPOLY
#if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__))
#include "verified/Hacl_Poly1305_64.h"
#else
#include "poly1305.h"
#endif
#include "chacha20.h"
#include "chacha20poly1305.h"
#endif
@ -22,6 +26,49 @@
/* Poly1305Do writes the Poly1305 authenticator of the given additional data
* and ciphertext to |out|. */
#ifndef NSS_DISABLE_CHACHAPOLY
#if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__))
static void
Poly1305PadUpdate(Hacl_Impl_Poly1305_64_State_poly1305_state state, unsigned char *block, const unsigned char *p, const unsigned int pLen)
{
unsigned int pRemLen = pLen % 16;
Hacl_Poly1305_64_update(state, (uint8_t *)p, (pLen / 16));
if (pRemLen > 0) {
memcpy(block, p + (pLen - pRemLen), pRemLen);
Hacl_Poly1305_64_update(state, block, 1);
}
}
static void
Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen,
const unsigned char *ciphertext, unsigned int ciphertextLen,
const unsigned char key[32])
{
uint64_t tmp1[6U] = { 0U };
Hacl_Impl_Poly1305_64_State_poly1305_state state = Hacl_Poly1305_64_mk_state(tmp1, tmp1 + 3);
unsigned char block[16] = { 0 };
Hacl_Poly1305_64_init(state, (uint8_t *)key);
Poly1305PadUpdate(state, block, ad, adLen);
memset(block, 0, 16);
Poly1305PadUpdate(state, block, ciphertext, ciphertextLen);
unsigned int i;
unsigned int j;
for (i = 0, j = adLen; i < 8; i++, j >>= 8) {
block[i] = j;
}
for (i = 8, j = ciphertextLen; i < 16; i++, j >>= 8) {
block[i] = j;
}
Hacl_Poly1305_64_update(state, block, 1);
Hacl_Poly1305_64_finish(state, out, (uint8_t *)(key + 16));
}
#else
static void
Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen,
const unsigned char *ciphertext, unsigned int ciphertextLen,
@ -56,7 +103,9 @@ Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen,
Poly1305Update(&state, lengthBytes, sizeof(lengthBytes));
Poly1305Finish(&state, out);
}
#endif
#endif /* HAVE_INT128_SUPPORT */
#endif /* NSS_DISABLE_CHACHAPOLY */
SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,

View file

@ -90,7 +90,12 @@ EXTRA_SHARED_LIBS += \
endif
endif
ifeq ($(OS_ARCH), Linux)
CFLAGS += -std=gnu99
endif
ifeq ($(OS_ARCH), Darwin)
CFLAGS += -std=gnu99
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
endif

View file

@ -0,0 +1,36 @@
/* 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
/* This file holds useful functions and macros for crypto code. */
#include "crypto_primitives.h"
/*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
__inline__ PRUint64
swap8b(PRUint64 value)
{
__asm__("bswapq %0"
: "+r"(value));
return (value);
}
#elif !defined(_MSC_VER)
PRUint64
swap8b(PRUint64 x)
{
PRUint64 t1 = x;
t1 = ((t1 & SHA_MASK8) << 8) | ((t1 >> 8) & SHA_MASK8);
t1 = ((t1 & SHA_MASK16) << 16) | ((t1 >> 16) & SHA_MASK16);
return (t1 >> 32) | (t1 << 32);
}
#endif

View file

@ -0,0 +1,51 @@
/* 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/. */
/* This file holds useful functions and macros for crypto code. */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include <stdlib.h>
#include "prtypes.h"
/* Unfortunately this isn't always set when it should be. */
#if defined(HAVE_LONG_LONG)
/*
* ROTR64/ROTL64(x, n): rotate a 64-bit integer x by n bites to the right/left.
*/
#if defined(_MSC_VER)
#pragma intrinsic(_rotr64, _rotl64)
#define ROTR64(x, n) _rotr64((x), (n))
#define ROTL64(x, n) _rotl64((x), (n))
#else
#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
#endif
/*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/
#if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64)
#define FREEBL_HTONLL(x) _byteswap_uint64(x)
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
PRUint64 swap8b(PRUint64 value);
#define FREEBL_HTONLL(x) swap8b(x)
#else
#define SHA_MASK16 0x0000FFFF0000FFFFULL
#define SHA_MASK8 0x00FF00FF00FF00FFULL
PRUint64 swap8b(PRUint64 x);
#define FREEBL_HTONLL(x) swap8b(x)
#endif /* _MSC_VER */
#endif /* HAVE_LONG_LONG */

View file

@ -8,19 +8,22 @@
#include "nssilock.h"
#include "seccomon.h"
#include "secerr.h"
#include "prinit.h"
#define GLOBAL_BYTES_SIZE 100
static PRUint8 globalBytes[GLOBAL_BYTES_SIZE];
static unsigned long globalNumCalls = 0;
static PZLock *rng_lock = NULL;
static PRCallOnceType coRNGInit;
static const PRCallOnceType pristineCallOnce;
SECStatus
RNG_RNGInit(void)
static PRStatus
rng_init(void)
{
rng_lock = PZ_NewLock(nssILockOther);
if (!rng_lock) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
return PR_FAILURE;
}
/* --- LOCKED --- */
PZ_Lock(rng_lock);
@ -28,6 +31,17 @@ RNG_RNGInit(void)
PZ_Unlock(rng_lock);
/* --- UNLOCKED --- */
return PR_SUCCESS;
}
SECStatus
RNG_RNGInit(void)
{
/* Allow only one call to initialize the context */
if (PR_CallOnce(&coRNGInit, rng_init) != PR_SUCCESS) {
return SECFailure;
}
return SECSuccess;
}
@ -97,8 +111,11 @@ RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
void
RNG_RNGShutdown(void)
{
PZ_DestroyLock(rng_lock);
rng_lock = NULL;
if (rng_lock) {
PZ_DestroyLock(rng_lock);
rng_lock = NULL;
}
coRNGInit = pristineCallOnce;
}
/* Test functions are not implemented! */

View file

@ -15,8 +15,6 @@
#include "ec.h"
#include "ecl.h"
#ifndef NSS_DISABLE_ECC
static const ECMethod kMethods[] = {
{ ECCurve25519,
ec_Curve25519_pt_mul,
@ -183,7 +181,6 @@ cleanup:
return rv;
}
#endif /* NSS_DISABLE_ECC */
/* Generates a new EC key pair. The private key is a supplied
* value and the public key is the result of performing a scalar
@ -194,7 +191,6 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
const unsigned char *privKeyBytes, int privKeyLen)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
PLArenaPool *arena;
ECPrivateKey *key;
mp_int k;
@ -309,9 +305,6 @@ cleanup:
printf("ec_NewKey returning %s\n",
(rv == SECSuccess) ? "success" : "failure");
#endif
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}
@ -326,15 +319,10 @@ EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
const unsigned char *seed, int seedlen)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
rv = ec_NewKey(ecParams, privKey, seed, seedlen);
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}
#ifndef NSS_DISABLE_ECC
/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
* modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
* random number generator.
@ -391,7 +379,6 @@ cleanup:
}
return privKeyBytes;
}
#endif /* NSS_DISABLE_ECC */
/* Generates a new EC key pair. The private key is a random value and
* the public key is the result of performing a scalar point multiplication
@ -401,7 +388,6 @@ SECStatus
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
int len;
unsigned char *privKeyBytes = NULL;
@ -425,9 +411,6 @@ cleanup:
printf("EC_NewKey returning %s\n",
(rv == SECSuccess) ? "success" : "failure");
#endif
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}
@ -441,7 +424,6 @@ cleanup:
SECStatus
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
{
#ifndef NSS_DISABLE_ECC
mp_int Px, Py;
ECGroup *group = NULL;
SECStatus rv = SECFailure;
@ -525,10 +507,6 @@ cleanup:
rv = SECFailure;
}
return rv;
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
return SECFailure;
#endif /* NSS_DISABLE_ECC */
}
/*
@ -549,7 +527,6 @@ ECDH_Derive(SECItem *publicValue,
SECItem *derivedSecret)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
unsigned int len = 0;
SECItem pointQ = { siBuffer, NULL, 0 };
mp_int k; /* to hold the private value */
@ -589,7 +566,11 @@ ECDH_Derive(SECItem *publicValue,
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
return method->mul(derivedSecret, privateValue, publicValue);
rv = method->mul(derivedSecret, privateValue, publicValue);
if (rv != SECSuccess) {
SECITEM_ZfreeItem(derivedSecret, PR_FALSE);
}
return rv;
}
/*
@ -654,9 +635,6 @@ cleanup:
if (pointQ.data) {
PORT_ZFree(pointQ.data, pointQ.len);
}
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}
@ -670,7 +648,6 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
const SECItem *digest, const unsigned char *kb, const int kblen)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
mp_int x1;
mp_int d, k; /* private key, random integer */
mp_int r, s; /* tuple (r, s) is the signature */
@ -899,9 +876,6 @@ cleanup:
printf("ECDSA signing with seed %s\n",
(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}
@ -914,7 +888,6 @@ SECStatus
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
int len;
unsigned char *kBytes = NULL;
@ -941,9 +914,6 @@ cleanup:
printf("ECDSA signing %s\n",
(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}
@ -961,7 +931,6 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
const SECItem *digest)
{
SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
mp_int r_, s_; /* tuple (r', s') is received signature) */
mp_int c, u1, u2, v; /* intermediate values used in verification */
mp_int x1;
@ -1161,9 +1130,6 @@ cleanup:
printf("ECDSA verification %s\n",
(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */
return rv;
}

View file

@ -2,8 +2,6 @@
* 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 NSS_DISABLE_ECC
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
@ -252,5 +250,3 @@ EC_GetPointSize(const ECParams *params)
}
return curveParams->pointSize - 1;
}
#endif /* NSS_DISABLE_ECC */

View file

@ -2,513 +2,13 @@
* 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/. */
/*
* Derived from public domain C code by Adan Langley and Daniel J. Bernstein
*/
#include "uint128.h"
#include "ecl-priv.h"
#include "mpi.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef uint8_t u8;
typedef uint64_t felem;
/* Sum two numbers: output += in */
static void
fsum(felem *output, const felem *in)
{
unsigned i;
for (i = 0; i < 5; ++i) {
output[i] += in[i];
}
}
/* Find the difference of two numbers: output = in - output
* (note the order of the arguments!)
*/
static void
fdifference_backwards(felem *ioutput, const felem *iin)
{
static const int64_t twotothe51 = ((int64_t)1l << 51);
const int64_t *in = (const int64_t *)iin;
int64_t *out = (int64_t *)ioutput;
out[0] = in[0] - out[0];
out[1] = in[1] - out[1];
out[2] = in[2] - out[2];
out[3] = in[3] - out[3];
out[4] = in[4] - out[4];
// An arithmetic shift right of 63 places turns a positive number to 0 and a
// negative number to all 1's. This gives us a bitmask that lets us avoid
// side-channel prone branches.
int64_t t;
#define NEGCHAIN(a, b) \
t = out[a] >> 63; \
out[a] += twotothe51 & t; \
out[b] -= 1 & t;
#define NEGCHAIN19(a, b) \
t = out[a] >> 63; \
out[a] += twotothe51 & t; \
out[b] -= 19 & t;
NEGCHAIN(0, 1);
NEGCHAIN(1, 2);
NEGCHAIN(2, 3);
NEGCHAIN(3, 4);
NEGCHAIN19(4, 0);
NEGCHAIN(0, 1);
NEGCHAIN(1, 2);
NEGCHAIN(2, 3);
NEGCHAIN(3, 4);
}
/* Multiply a number by a scalar: output = in * scalar */
static void
fscalar_product(felem *output, const felem *in,
const felem scalar)
{
uint128_t tmp, tmp2;
tmp = mul6464(in[0], scalar);
output[0] = mask51(tmp);
tmp2 = mul6464(in[1], scalar);
tmp = add128(tmp2, rshift128(tmp, 51));
output[1] = mask51(tmp);
tmp2 = mul6464(in[2], scalar);
tmp = add128(tmp2, rshift128(tmp, 51));
output[2] = mask51(tmp);
tmp2 = mul6464(in[3], scalar);
tmp = add128(tmp2, rshift128(tmp, 51));
output[3] = mask51(tmp);
tmp2 = mul6464(in[4], scalar);
tmp = add128(tmp2, rshift128(tmp, 51));
output[4] = mask51(tmp);
output[0] += mask_lower(rshift128(tmp, 51)) * 19;
}
/* Multiply two numbers: output = in2 * in
*
* output must be distinct to both inputs. The inputs are reduced coefficient
* form, the output is not.
*/
static void
fmul(felem *output, const felem *in2, const felem *in)
{
uint128_t t0, t1, t2, t3, t4, t5, t6, t7, t8;
t0 = mul6464(in[0], in2[0]);
t1 = add128(mul6464(in[1], in2[0]), mul6464(in[0], in2[1]));
t2 = add128(add128(mul6464(in[0], in2[2]),
mul6464(in[2], in2[0])),
mul6464(in[1], in2[1]));
t3 = add128(add128(add128(mul6464(in[0], in2[3]),
mul6464(in[3], in2[0])),
mul6464(in[1], in2[2])),
mul6464(in[2], in2[1]));
t4 = add128(add128(add128(add128(mul6464(in[0], in2[4]),
mul6464(in[4], in2[0])),
mul6464(in[3], in2[1])),
mul6464(in[1], in2[3])),
mul6464(in[2], in2[2]));
t5 = add128(add128(add128(mul6464(in[4], in2[1]),
mul6464(in[1], in2[4])),
mul6464(in[2], in2[3])),
mul6464(in[3], in2[2]));
t6 = add128(add128(mul6464(in[4], in2[2]),
mul6464(in[2], in2[4])),
mul6464(in[3], in2[3]));
t7 = add128(mul6464(in[3], in2[4]), mul6464(in[4], in2[3]));
t8 = mul6464(in[4], in2[4]);
t0 = add128(t0, mul12819(t5));
t1 = add128(t1, mul12819(t6));
t2 = add128(t2, mul12819(t7));
t3 = add128(t3, mul12819(t8));
t1 = add128(t1, rshift128(t0, 51));
t0 = mask51full(t0);
t2 = add128(t2, rshift128(t1, 51));
t1 = mask51full(t1);
t3 = add128(t3, rshift128(t2, 51));
t4 = add128(t4, rshift128(t3, 51));
t0 = add128(t0, mul12819(rshift128(t4, 51)));
t1 = add128(t1, rshift128(t0, 51));
t2 = mask51full(t2);
t2 = add128(t2, rshift128(t1, 51));
output[0] = mask51(t0);
output[1] = mask51(t1);
output[2] = mask_lower(t2);
output[3] = mask51(t3);
output[4] = mask51(t4);
}
static void
fsquare(felem *output, const felem *in)
{
uint128_t t0, t1, t2, t3, t4, t5, t6, t7, t8;
t0 = mul6464(in[0], in[0]);
t1 = lshift128(mul6464(in[0], in[1]), 1);
t2 = add128(lshift128(mul6464(in[0], in[2]), 1),
mul6464(in[1], in[1]));
t3 = add128(lshift128(mul6464(in[0], in[3]), 1),
lshift128(mul6464(in[1], in[2]), 1));
t4 = add128(add128(lshift128(mul6464(in[0], in[4]), 1),
lshift128(mul6464(in[3], in[1]), 1)),
mul6464(in[2], in[2]));
t5 = add128(lshift128(mul6464(in[4], in[1]), 1),
lshift128(mul6464(in[2], in[3]), 1));
t6 = add128(lshift128(mul6464(in[4], in[2]), 1),
mul6464(in[3], in[3]));
t7 = lshift128(mul6464(in[3], in[4]), 1);
t8 = mul6464(in[4], in[4]);
t0 = add128(t0, mul12819(t5));
t1 = add128(t1, mul12819(t6));
t2 = add128(t2, mul12819(t7));
t3 = add128(t3, mul12819(t8));
t1 = add128(t1, rshift128(t0, 51));
t0 = mask51full(t0);
t2 = add128(t2, rshift128(t1, 51));
t1 = mask51full(t1);
t3 = add128(t3, rshift128(t2, 51));
t4 = add128(t4, rshift128(t3, 51));
t0 = add128(t0, mul12819(rshift128(t4, 51)));
t1 = add128(t1, rshift128(t0, 51));
output[0] = mask51(t0);
output[1] = mask_lower(t1);
output[2] = mask51(t2);
output[3] = mask51(t3);
output[4] = mask51(t4);
}
/* Take a 32-byte number and expand it into polynomial form */
static void NO_SANITIZE_ALIGNMENT
fexpand(felem *output, const u8 *in)
{
output[0] = *((const uint64_t *)(in)) & MASK51;
output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51;
output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51;
output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51;
output[4] = (*((const uint64_t *)(in + 24)) >> 12) & MASK51;
}
/* Take a fully reduced polynomial form number and contract it into a
* 32-byte array
*/
static void
fcontract(u8 *output, const felem *input)
{
uint128_t t0 = init128x(input[0]);
uint128_t t1 = init128x(input[1]);
uint128_t t2 = init128x(input[2]);
uint128_t t3 = init128x(input[3]);
uint128_t t4 = init128x(input[4]);
uint128_t tmp = init128x(19);
t1 = add128(t1, rshift128(t0, 51));
t0 = mask51full(t0);
t2 = add128(t2, rshift128(t1, 51));
t1 = mask51full(t1);
t3 = add128(t3, rshift128(t2, 51));
t2 = mask51full(t2);
t4 = add128(t4, rshift128(t3, 51));
t3 = mask51full(t3);
t0 = add128(t0, mul12819(rshift128(t4, 51)));
t4 = mask51full(t4);
t1 = add128(t1, rshift128(t0, 51));
t0 = mask51full(t0);
t2 = add128(t2, rshift128(t1, 51));
t1 = mask51full(t1);
t3 = add128(t3, rshift128(t2, 51));
t2 = mask51full(t2);
t4 = add128(t4, rshift128(t3, 51));
t3 = mask51full(t3);
t0 = add128(t0, mul12819(rshift128(t4, 51)));
t4 = mask51full(t4);
/* now t is between 0 and 2^255-1, properly carried. */
/* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
t0 = add128(t0, tmp);
t1 = add128(t1, rshift128(t0, 51));
t0 = mask51full(t0);
t2 = add128(t2, rshift128(t1, 51));
t1 = mask51full(t1);
t3 = add128(t3, rshift128(t2, 51));
t2 = mask51full(t2);
t4 = add128(t4, rshift128(t3, 51));
t3 = mask51full(t3);
t0 = add128(t0, mul12819(rshift128(t4, 51)));
t4 = mask51full(t4);
/* now between 19 and 2^255-1 in both cases, and offset by 19. */
t0 = add128(t0, init128x(0x8000000000000 - 19));
tmp = init128x(0x8000000000000 - 1);
t1 = add128(t1, tmp);
t2 = add128(t2, tmp);
t3 = add128(t3, tmp);
t4 = add128(t4, tmp);
/* now between 2^255 and 2^256-20, and offset by 2^255. */
t1 = add128(t1, rshift128(t0, 51));
t0 = mask51full(t0);
t2 = add128(t2, rshift128(t1, 51));
t1 = mask51full(t1);
t3 = add128(t3, rshift128(t2, 51));
t2 = mask51full(t2);
t4 = add128(t4, rshift128(t3, 51));
t3 = mask51full(t3);
t4 = mask51full(t4);
*((uint64_t *)(output)) = mask_lower(t0) | mask_lower(t1) << 51;
*((uint64_t *)(output + 8)) = (mask_lower(t1) >> 13) | (mask_lower(t2) << 38);
*((uint64_t *)(output + 16)) = (mask_lower(t2) >> 26) | (mask_lower(t3) << 25);
*((uint64_t *)(output + 24)) = (mask_lower(t3) >> 39) | (mask_lower(t4) << 12);
}
/* Input: Q, Q', Q-Q'
* Output: 2Q, Q+Q'
*
* x2 z3: long form
* x3 z3: long form
* x z: short form, destroyed
* xprime zprime: short form, destroyed
* qmqp: short form, preserved
*/
static void
fmonty(felem *x2, felem *z2, /* output 2Q */
felem *x3, felem *z3, /* output Q + Q' */
felem *x, felem *z, /* input Q */
felem *xprime, felem *zprime, /* input Q' */
const felem *qmqp /* input Q - Q' */)
{
felem origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5], zzprime[5],
zzzprime[5];
memcpy(origx, x, 5 * sizeof(felem));
fsum(x, z);
fdifference_backwards(z, origx); // does x - z
memcpy(origxprime, xprime, sizeof(felem) * 5);
fsum(xprime, zprime);
fdifference_backwards(zprime, origxprime);
fmul(xxprime, xprime, z);
fmul(zzprime, x, zprime);
memcpy(origxprime, xxprime, sizeof(felem) * 5);
fsum(xxprime, zzprime);
fdifference_backwards(zzprime, origxprime);
fsquare(x3, xxprime);
fsquare(zzzprime, zzprime);
fmul(z3, zzzprime, qmqp);
fsquare(xx, x);
fsquare(zz, z);
fmul(x2, xx, zz);
fdifference_backwards(zz, xx); // does zz = xx - zz
fscalar_product(zzz, zz, 121665);
fsum(zzz, xx);
fmul(z2, zz, zzz);
}
// -----------------------------------------------------------------------------
// Maybe swap the contents of two felem arrays (@a and @b), each @len elements
// long. Perform the swap iff @swap is non-zero.
//
// This function performs the swap without leaking any side-channel
// information.
// -----------------------------------------------------------------------------
static void
swap_conditional(felem *a, felem *b, unsigned len, felem iswap)
{
unsigned i;
const felem swap = 1 + ~iswap;
for (i = 0; i < len; ++i) {
const felem x = swap & (a[i] ^ b[i]);
a[i] ^= x;
b[i] ^= x;
}
}
/* Calculates nQ where Q is the x-coordinate of a point on the curve
*
* resultx/resultz: the x coordinate of the resulting curve point (short form)
* n: a 32-byte number
* q: a point of the curve (short form)
*/
static void
cmult(felem *resultx, felem *resultz, const u8 *n, const felem *q)
{
felem a[5] = { 0 }, b[5] = { 1 }, c[5] = { 1 }, d[5] = { 0 };
felem *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
felem e[5] = { 0 }, f[5] = { 1 }, g[5] = { 0 }, h[5] = { 1 };
felem *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
unsigned i, j;
memcpy(nqpqx, q, sizeof(felem) * 5);
for (i = 0; i < 32; ++i) {
u8 byte = n[31 - i];
for (j = 0; j < 8; ++j) {
const felem bit = byte >> 7;
swap_conditional(nqx, nqpqx, 5, bit);
swap_conditional(nqz, nqpqz, 5, bit);
fmonty(nqx2, nqz2, nqpqx2, nqpqz2, nqx, nqz, nqpqx, nqpqz, q);
swap_conditional(nqx2, nqpqx2, 5, bit);
swap_conditional(nqz2, nqpqz2, 5, bit);
t = nqx;
nqx = nqx2;
nqx2 = t;
t = nqz;
nqz = nqz2;
nqz2 = t;
t = nqpqx;
nqpqx = nqpqx2;
nqpqx2 = t;
t = nqpqz;
nqpqz = nqpqz2;
nqpqz2 = t;
byte <<= 1;
}
}
memcpy(resultx, nqx, sizeof(felem) * 5);
memcpy(resultz, nqz, sizeof(felem) * 5);
}
// -----------------------------------------------------------------------------
// Shamelessly copied from djb's code
// -----------------------------------------------------------------------------
static void
crecip(felem *out, const felem *z)
{
felem z2[5];
felem z9[5];
felem z11[5];
felem z2_5_0[5];
felem z2_10_0[5];
felem z2_20_0[5];
felem z2_50_0[5];
felem z2_100_0[5];
felem t0[5];
felem t1[5];
int i;
/* 2 */ fsquare(z2, z);
/* 4 */ fsquare(t1, z2);
/* 8 */ fsquare(t0, t1);
/* 9 */ fmul(z9, t0, z);
/* 11 */ fmul(z11, z9, z2);
/* 22 */ fsquare(t0, z11);
/* 2^5 - 2^0 = 31 */ fmul(z2_5_0, t0, z9);
/* 2^6 - 2^1 */ fsquare(t0, z2_5_0);
/* 2^7 - 2^2 */ fsquare(t1, t0);
/* 2^8 - 2^3 */ fsquare(t0, t1);
/* 2^9 - 2^4 */ fsquare(t1, t0);
/* 2^10 - 2^5 */ fsquare(t0, t1);
/* 2^10 - 2^0 */ fmul(z2_10_0, t0, z2_5_0);
/* 2^11 - 2^1 */ fsquare(t0, z2_10_0);
/* 2^12 - 2^2 */ fsquare(t1, t0);
/* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^20 - 2^0 */ fmul(z2_20_0, t1, z2_10_0);
/* 2^21 - 2^1 */ fsquare(t0, z2_20_0);
/* 2^22 - 2^2 */ fsquare(t1, t0);
/* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^40 - 2^0 */ fmul(t0, t1, z2_20_0);
/* 2^41 - 2^1 */ fsquare(t1, t0);
/* 2^42 - 2^2 */ fsquare(t0, t1);
/* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) {
fsquare(t1, t0);
fsquare(t0, t1);
}
/* 2^50 - 2^0 */ fmul(z2_50_0, t0, z2_10_0);
/* 2^51 - 2^1 */ fsquare(t0, z2_50_0);
/* 2^52 - 2^2 */ fsquare(t1, t0);
/* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^100 - 2^0 */ fmul(z2_100_0, t1, z2_50_0);
/* 2^101 - 2^1 */ fsquare(t1, z2_100_0);
/* 2^102 - 2^2 */ fsquare(t0, t1);
/* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) {
fsquare(t1, t0);
fsquare(t0, t1);
}
/* 2^200 - 2^0 */ fmul(t1, t0, z2_100_0);
/* 2^201 - 2^1 */ fsquare(t0, t1);
/* 2^202 - 2^2 */ fsquare(t1, t0);
/* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) {
fsquare(t0, t1);
fsquare(t1, t0);
}
/* 2^250 - 2^0 */ fmul(t0, t1, z2_50_0);
/* 2^251 - 2^1 */ fsquare(t1, t0);
/* 2^252 - 2^2 */ fsquare(t0, t1);
/* 2^253 - 2^3 */ fsquare(t1, t0);
/* 2^254 - 2^4 */ fsquare(t0, t1);
/* 2^255 - 2^5 */ fsquare(t1, t0);
/* 2^255 - 21 */ fmul(out, t1, z11);
}
#include "../verified/Hacl_Curve25519.h"
SECStatus
ec_Curve25519_mul(uint8_t *mypublic, const uint8_t *secret,
const uint8_t *basepoint)
ec_Curve25519_mul(uint8_t *mypublic, const uint8_t *secret, const uint8_t *basepoint)
{
felem bp[5], x[5], z[5], zmone[5];
uint8_t e[32];
int i;
for (i = 0; i < 32; ++i) {
e[i] = secret[i];
}
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
fexpand(bp, basepoint);
cmult(x, z, e, bp);
crecip(zmone, z);
fmul(z, x, zmone);
fcontract(mypublic, z);
// Note: this cast is safe because HaCl* state has a post-condition that only "mypublic" changed.
Hacl_Curve25519_crypto_scalarmult(mypublic, (uint8_t *)secret, (uint8_t *)basepoint);
return 0;
}

View file

@ -115,5 +115,9 @@ ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P)
px = P->data;
}
return ec_Curve25519_mul(X->data, k->data, px);
SECStatus rv = ec_Curve25519_mul(X->data, k->data, px);
if (NSS_SecureMemcmpZero(X->data, X->len) == 0) {
return SECFailure;
}
return rv;
}

View file

@ -29,6 +29,7 @@
'files': [
'alghmac.h',
'blapi.h',
'blake2b.h',
'chacha20poly1305.h',
'ec.h',
'ecl/ecl-curve.h',

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: fipstest.c,v 1.31 2012/06/28 17:55:06 rrelyea%redhat.com Exp $ */
#ifndef NSS_FIPS_DISABLED
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
@ -15,9 +16,7 @@
#include "secerr.h"
#include "prtypes.h"
#ifdef NSS_ENABLE_ECC
#include "ec.h" /* Required for ECDSA */
#endif
/*
* different platforms have different ways of calling and initial entry point
@ -1077,8 +1076,6 @@ rsa_loser:
return (SECFailure);
}
#ifdef NSS_ENABLE_ECC
static SECStatus
freebl_fips_ECDSA_Test(ECParams *ecparams,
const PRUint8 *knownSignature,
@ -1275,8 +1272,6 @@ freebl_fips_ECDSA_PowerUpSelfTest()
return (SECSuccess);
}
#endif /* NSS_ENABLE_ECC */
static SECStatus
freebl_fips_DSA_PowerUpSelfTest(void)
{
@ -1559,13 +1554,11 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
if (rv != SECSuccess)
return rv;
#ifdef NSS_ENABLE_ECC
/* ECDSA Power-Up SelfTest(s). */
rv = freebl_fips_ECDSA_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
#endif
}
/* Passed Power-Up SelfTest(s). */
return (SECSuccess);
@ -1589,9 +1582,6 @@ static PRBool self_tests_freebl_ran = PR_FALSE;
static PRBool self_tests_ran = PR_FALSE;
static PRBool self_tests_freebl_success = PR_FALSE;
static PRBool self_tests_success = PR_FALSE;
#if defined(DEBUG)
static PRBool fips_mode_available = PR_FALSE;
#endif
/*
* accessors for freebl
@ -1644,7 +1634,6 @@ bl_startup_tests(void)
PORT_Assert(self_tests_freebl_ran == PR_FALSE);
PORT_Assert(self_tests_success == PR_FALSE);
PORT_Assert(fips_mode_available == PR_FALSE);
self_tests_freebl_ran = PR_TRUE; /* we are running the tests */
self_tests_success = PR_FALSE; /* force it just in case */
self_tests_freebl_success = PR_FALSE; /* force it just in case */
@ -1713,3 +1702,4 @@ BL_FIPSEntryOK(PRBool freebl_only)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
#endif

View file

@ -22,6 +22,37 @@
'-mssse3'
]
},
{
'target_name': 'gcm-aes-x86_c_lib',
'type': 'static_library',
'sources': [
'gcm-x86.c', 'aes-x86.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
# Enable isa option for pclmul and aes-ni; supported since gcc 4.4.
# This is only supported by x84/x64. It's not needed for Windows,
# unless clang-cl is used.
'cflags_mozilla': [
'-mpclmul', '-maes'
],
'conditions': [
[ 'OS=="linux" or OS=="android" or OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
'cflags': [
'-mpclmul', '-maes'
],
}],
# macOS build doesn't use cflags.
[ 'OS=="mac"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-mpclmul', '-maes'
],
},
}]
]
},
{
'target_name': 'freebl',
'type': 'static_library',
@ -45,6 +76,11 @@
'<(DEPTH)/exports.gyp:nss_exports',
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
'dependencies': [
'gcm-aes-x86_c_lib'
],
}],
[ 'OS=="linux"', {
'defines!': [
'FREEBL_NO_DEPEND',
@ -76,6 +112,11 @@
'<(DEPTH)/exports.gyp:nss_exports',
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
'dependencies': [
'gcm-aes-x86_c_lib'
]
}],
[ 'OS!="linux" and OS!="android"', {
'conditions': [
[ 'moz_fold_libs==0', {
@ -142,7 +183,8 @@
'target_defaults': {
'include_dirs': [
'mpi',
'ecl'
'ecl',
'verified',
],
'defines': [
'SHLIB_SUFFIX=\"<(dll_suffix)\"',
@ -153,19 +195,12 @@
'MP_API_COMPATIBLE'
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
'cflags_mozilla': [
'-mpclmul',
'-maes',
],
}],
[ 'OS=="mac"', {
'xcode_settings': {
# I'm not sure since when this is supported.
# But I hope that doesn't matter. We also assume this is x86/x64.
'OTHER_CFLAGS': [
'-mpclmul',
'-maes',
'-std=gnu99',
],
},
}],
@ -221,17 +256,24 @@
'HAVE_INT128_SUPPORT',
],
}, {
'sources': [
'ecl/uint128.c',
'defines': [
'KRML_NOUINT128',
],
}],
],
}, {
'defines': [
'KRML_NOUINT128',
],
}],
[ 'OS=="linux"', {
'defines': [
'FREEBL_LOWHASH',
'FREEBL_NO_DEPEND',
],
'cflags': [
'-std=gnu99',
],
}],
[ 'OS=="linux" or OS=="android"', {
'conditions': [
@ -259,14 +301,6 @@
'MP_USE_UINT_DIGIT',
],
}],
[ 'target_arch=="ia32" or target_arch=="x64"', {
'cflags': [
# enable isa option for pclmul am aes-ni; supported since gcc 4.4
# This is only support by x84/x64. It's not needed for Windows.
'-mpclmul',
'-maes',
],
}],
[ 'target_arch=="arm"', {
'defines': [
'MP_ASSEMBLY_MULTIPLY',

View file

@ -8,8 +8,10 @@
'alghmac.c',
'arcfive.c',
'arcfour.c',
'blake2b.c',
'camellia.c',
'chacha20poly1305.c',
'crypto_primitives.c',
'ctr.c',
'cts.c',
'des.c',
@ -98,10 +100,6 @@
],
}],
[ 'OS=="win"', {
'sources': [
#TODO: building with mingw should not need this.
'ecl/uint128.c',
],
'libraries': [
'advapi32.lib',
],
@ -132,29 +130,53 @@
}],
],
}],
['target_arch=="ia32" or target_arch=="x64"', {
['target_arch=="ia32" or target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', {
'sources': [
# All intel architectures get the 64 bit version
# All intel and 64-bit ARM architectures get the 64 bit version.
'ecl/curve25519_64.c',
'verified/Hacl_Curve25519.c',
'verified/FStar.c',
],
}, {
'sources': [
# All non intel architectures get the generic 32 bit implementation (slow!)
# All other architectures get the generic 32 bit implementation (slow!)
'ecl/curve25519_32.c',
],
}],
#TODO uint128.c
[ 'disable_chachapoly==0', {
'conditions': [
[ 'OS!="win" and target_arch=="x64"', {
'sources': [
'chacha20_vec.c',
'poly1305-donna-x64-sse2-incremental-source.c',
[ 'OS!="win"', {
'conditions': [
[ 'target_arch=="x64"', {
'sources': [
'chacha20_vec.c',
'verified/Hacl_Poly1305_64.c',
],
}, {
# !Windows & !x64
'conditions': [
[ 'target_arch=="arm64" or target_arch=="aarch64"', {
'sources': [
'chacha20.c',
'verified/Hacl_Chacha20.c',
'verified/Hacl_Poly1305_64.c',
],
}, {
# !Windows & !x64 & !arm64 & !aarch64
'sources': [
'chacha20.c',
'verified/Hacl_Chacha20.c',
'poly1305.c',
],
}],
],
}],
],
}, {
# not x64
# Windows
'sources': [
'chacha20.c',
'verified/Hacl_Chacha20.c',
'poly1305.c',
],
}],

View file

@ -0,0 +1,127 @@
/* 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 "gcm.h"
#include "secerr.h"
#include <wmmintrin.h> /* clmul */
#define WRITE64(x, bytes) \
(bytes)[0] = (x) >> 56; \
(bytes)[1] = (x) >> 48; \
(bytes)[2] = (x) >> 40; \
(bytes)[3] = (x) >> 32; \
(bytes)[4] = (x) >> 24; \
(bytes)[5] = (x) >> 16; \
(bytes)[6] = (x) >> 8; \
(bytes)[7] = (x);
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
uint64_t tmp_out[2];
_mm_storeu_si128((__m128i *)tmp_out, ghash->x);
/* maxout must be larger than 16 byte (checked by the caller). */
WRITE64(tmp_out[0], outbuf + 8);
WRITE64(tmp_out[1], outbuf);
return SECSuccess;
}
SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
size_t i;
pre_align __m128i z_high post_align;
pre_align __m128i z_low post_align;
pre_align __m128i C post_align;
pre_align __m128i D post_align;
pre_align __m128i E post_align;
pre_align __m128i F post_align;
pre_align __m128i bin post_align;
pre_align __m128i Ci post_align;
pre_align __m128i tmp post_align;
for (i = 0; i < count; i++, buf += 16) {
bin = _mm_set_epi16(((uint16_t)buf[0] << 8) | buf[1],
((uint16_t)buf[2] << 8) | buf[3],
((uint16_t)buf[4] << 8) | buf[5],
((uint16_t)buf[6] << 8) | buf[7],
((uint16_t)buf[8] << 8) | buf[9],
((uint16_t)buf[10] << 8) | buf[11],
((uint16_t)buf[12] << 8) | buf[13],
((uint16_t)buf[14] << 8) | buf[15]);
Ci = _mm_xor_si128(bin, ghash->x);
/* Do binary mult ghash->X = Ci * ghash->H. */
C = _mm_clmulepi64_si128(Ci, ghash->h, 0x00);
D = _mm_clmulepi64_si128(Ci, ghash->h, 0x11);
E = _mm_clmulepi64_si128(Ci, ghash->h, 0x01);
F = _mm_clmulepi64_si128(Ci, ghash->h, 0x10);
tmp = _mm_xor_si128(E, F);
z_high = _mm_xor_si128(tmp, _mm_slli_si128(D, 8));
z_high = _mm_unpackhi_epi64(z_high, D);
z_low = _mm_xor_si128(_mm_slli_si128(tmp, 8), C);
z_low = _mm_unpackhi_epi64(_mm_slli_si128(C, 8), z_low);
/* Shift one to the left (multiply by x) as gcm spec is stupid. */
C = _mm_slli_si128(z_low, 8);
E = _mm_srli_epi64(C, 63);
D = _mm_slli_si128(z_high, 8);
F = _mm_srli_epi64(D, 63);
/* Carry over */
C = _mm_srli_si128(z_low, 8);
D = _mm_srli_epi64(C, 63);
z_low = _mm_or_si128(_mm_slli_epi64(z_low, 1), E);
z_high = _mm_or_si128(_mm_or_si128(_mm_slli_epi64(z_high, 1), F), D);
/* Reduce */
C = _mm_slli_si128(z_low, 8);
/* D = z_low << 127 */
D = _mm_slli_epi64(C, 63);
/* E = z_low << 126 */
E = _mm_slli_epi64(C, 62);
/* F = z_low << 121 */
F = _mm_slli_epi64(C, 57);
/* z_low ^= (z_low << 127) ^ (z_low << 126) ^ (z_low << 121); */
z_low = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(z_low, D), E), F);
C = _mm_srli_si128(z_low, 8);
/* D = z_low >> 1 */
D = _mm_slli_epi64(C, 63);
D = _mm_or_si128(_mm_srli_epi64(z_low, 1), D);
/* E = z_low >> 2 */
E = _mm_slli_epi64(C, 62);
E = _mm_or_si128(_mm_srli_epi64(z_low, 2), E);
/* F = z_low >> 7 */
F = _mm_slli_epi64(C, 57);
F = _mm_or_si128(_mm_srli_epi64(z_low, 7), F);
/* ghash->x ^= z_low ^ (z_low >> 1) ^ (z_low >> 2) ^ (z_low >> 7); */
ghash->x = _mm_xor_si128(_mm_xor_si128(
_mm_xor_si128(_mm_xor_si128(z_high, z_low), D), E),
F);
}
return SECSuccess;
}
SECStatus
gcm_HashInit_hw(gcmHashContext *ghash)
{
ghash->ghash_mul = gcm_HashMult_hw;
ghash->x = _mm_setzero_si128();
/* MSVC requires __m64 to load epi64. */
ghash->h = _mm_set_epi32(ghash->h_high >> 32, (uint32_t)ghash->h_high,
ghash->h_low >> 32, (uint32_t)ghash->h_low);
ghash->hw = PR_TRUE;
return SECSuccess;
}
SECStatus
gcm_HashZeroX_hw(gcmHashContext *ghash)
{
ghash->x = _mm_setzero_si128();
return SECSuccess;
}

View file

@ -17,18 +17,50 @@
#include <limits.h>
#ifdef NSS_X86_OR_X64
#include <wmmintrin.h> /* clmul */
#endif
/* Forward declarations */
SECStatus gcm_HashInit_hw(gcmHashContext *ghash);
SECStatus gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf);
SECStatus gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count);
SECStatus gcm_HashZeroX_hw(gcmHashContext *ghash);
SECStatus gcm_HashMult_sftw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count);
SECStatus gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count);
/* Stub definitions for the above *_hw functions, which shouldn't be
* used unless NSS_X86_OR_X64 is defined */
#ifndef NSS_X86_OR_X64
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
SECStatus
gcm_HashInit_hw(gcmHashContext *ghash)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
SECStatus
gcm_HashZeroX_hw(gcmHashContext *ghash)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
#endif /* NSS_X86_OR_X64 */
uint64_t
get64(const unsigned char *bytes)
{
@ -46,6 +78,8 @@ get64(const unsigned char *bytes)
SECStatus
gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
{
SECStatus rv = SECSuccess;
ghash->cLen = 0;
ghash->bufLen = 0;
PORT_Memset(ghash->counterBuf, 0, sizeof(ghash->counterBuf));
@ -53,17 +87,7 @@ gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
ghash->h_low = get64(H + 8);
ghash->h_high = get64(H);
if (clmul_support() && !sw) {
#ifdef NSS_X86_OR_X64
ghash->ghash_mul = gcm_HashMult_hw;
ghash->x = _mm_setzero_si128();
/* MSVC requires __m64 to load epi64. */
ghash->h = _mm_set_epi32(ghash->h_high >> 32, (uint32_t)ghash->h_high,
ghash->h_low >> 32, (uint32_t)ghash->h_low);
ghash->hw = PR_TRUE;
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
rv = gcm_HashInit_hw(ghash);
} else {
/* We fall back to the software implementation if we can't use / don't
* want to use pclmul. */
@ -75,7 +99,7 @@ gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
ghash->x_high = ghash->x_low = 0;
ghash->hw = PR_FALSE;
}
return SECSuccess;
return rv;
}
#ifdef HAVE_INT128_SUPPORT
@ -283,102 +307,17 @@ gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
}
#endif /* HAVE_INT128_SUPPORT */
SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
#ifdef NSS_X86_OR_X64
size_t i;
pre_align __m128i z_high post_align;
pre_align __m128i z_low post_align;
pre_align __m128i C post_align;
pre_align __m128i D post_align;
pre_align __m128i E post_align;
pre_align __m128i F post_align;
pre_align __m128i bin post_align;
pre_align __m128i Ci post_align;
pre_align __m128i tmp post_align;
for (i = 0; i < count; i++, buf += 16) {
bin = _mm_set_epi16(((uint16_t)buf[0] << 8) | buf[1],
((uint16_t)buf[2] << 8) | buf[3],
((uint16_t)buf[4] << 8) | buf[5],
((uint16_t)buf[6] << 8) | buf[7],
((uint16_t)buf[8] << 8) | buf[9],
((uint16_t)buf[10] << 8) | buf[11],
((uint16_t)buf[12] << 8) | buf[13],
((uint16_t)buf[14] << 8) | buf[15]);
Ci = _mm_xor_si128(bin, ghash->x);
/* Do binary mult ghash->X = Ci * ghash->H. */
C = _mm_clmulepi64_si128(Ci, ghash->h, 0x00);
D = _mm_clmulepi64_si128(Ci, ghash->h, 0x11);
E = _mm_clmulepi64_si128(Ci, ghash->h, 0x01);
F = _mm_clmulepi64_si128(Ci, ghash->h, 0x10);
tmp = _mm_xor_si128(E, F);
z_high = _mm_xor_si128(tmp, _mm_slli_si128(D, 8));
z_high = _mm_unpackhi_epi64(z_high, D);
z_low = _mm_xor_si128(_mm_slli_si128(tmp, 8), C);
z_low = _mm_unpackhi_epi64(_mm_slli_si128(C, 8), z_low);
/* Shift one to the left (multiply by x) as gcm spec is stupid. */
C = _mm_slli_si128(z_low, 8);
E = _mm_srli_epi64(C, 63);
D = _mm_slli_si128(z_high, 8);
F = _mm_srli_epi64(D, 63);
/* Carry over */
C = _mm_srli_si128(z_low, 8);
D = _mm_srli_epi64(C, 63);
z_low = _mm_or_si128(_mm_slli_epi64(z_low, 1), E);
z_high = _mm_or_si128(_mm_or_si128(_mm_slli_epi64(z_high, 1), F), D);
/* Reduce */
C = _mm_slli_si128(z_low, 8);
/* D = z_low << 127 */
D = _mm_slli_epi64(C, 63);
/* E = z_low << 126 */
E = _mm_slli_epi64(C, 62);
/* F = z_low << 121 */
F = _mm_slli_epi64(C, 57);
/* z_low ^= (z_low << 127) ^ (z_low << 126) ^ (z_low << 121); */
z_low = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(z_low, D), E), F);
C = _mm_srli_si128(z_low, 8);
/* D = z_low >> 1 */
D = _mm_slli_epi64(C, 63);
D = _mm_or_si128(_mm_srli_epi64(z_low, 1), D);
/* E = z_low >> 2 */
E = _mm_slli_epi64(C, 62);
E = _mm_or_si128(_mm_srli_epi64(z_low, 2), E);
/* F = z_low >> 7 */
F = _mm_slli_epi64(C, 57);
F = _mm_or_si128(_mm_srli_epi64(z_low, 7), F);
/* ghash->x ^= z_low ^ (z_low >> 1) ^ (z_low >> 2) ^ (z_low >> 7); */
ghash->x = _mm_xor_si128(_mm_xor_si128(
_mm_xor_si128(_mm_xor_si128(z_high, z_low), D), E),
F);
}
return SECSuccess;
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
}
static SECStatus
gcm_zeroX(gcmHashContext *ghash)
{
SECStatus rv = SECSuccess;
if (ghash->hw) {
#ifdef NSS_X86_OR_X64
ghash->x = _mm_setzero_si128();
return SECSuccess;
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
rv = gcm_HashZeroX_hw(ghash);
}
ghash->x_high = ghash->x_low = 0;
return SECSuccess;
return rv;
}
/*
@ -503,15 +442,10 @@ gcmHash_Final(gcmHashContext *ghash, unsigned char *outbuf,
}
if (ghash->hw) {
#ifdef NSS_X86_OR_X64
uint64_t tmp_out[2];
_mm_storeu_si128((__m128i *)tmp_out, ghash->x);
WRITE64(tmp_out[0], T + 8);
WRITE64(tmp_out[1], T);
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
rv = gcm_HashWrite_hw(ghash, T);
if (rv != SECSuccess) {
goto cleanup;
}
} else {
WRITE64(ghash->x_low, T + 8);
WRITE64(ghash->x_high, T);
@ -595,14 +529,7 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
if (gcm == NULL) {
return NULL;
}
/* aligned_alloc is C11 so we have to do it the old way. */
ghash = PORT_ZAlloc(sizeof(gcmHashContext) + 15);
if (ghash == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
ghash->mem = ghash;
ghash = (gcmHashContext *)(((uintptr_t)ghash + 15) & ~(uintptr_t)0x0F);
ghash = PORT_ZNewAligned(gcmHashContext, 16, mem);
/* first plug in the ghash context */
gcm->ghash_context = ghash;

View file

@ -9,7 +9,21 @@
#include <stdint.h>
#ifdef NSS_X86_OR_X64
/* GCC <= 4.8 doesn't support including emmintrin.h without enabling SSE2 */
#if !defined(__clang__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && \
(__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
#pragma GCC push_options
#pragma GCC target("sse2")
#undef NSS_DISABLE_SSE2
#define NSS_DISABLE_SSE2 1
#endif /* GCC <= 4.8 */
#include <emmintrin.h> /* __m128i */
#ifdef NSS_DISABLE_SSE2
#undef NSS_DISABLE_SSE2
#pragma GCC pop_options
#endif /* NSS_DISABLE_SSE2 */
#endif
SEC_BEGIN_PROTOS

View file

@ -298,9 +298,25 @@ static const struct FREEBLVectorStr vector =
/* End of Version 3.018 */
EC_GetPointSize
EC_GetPointSize,
/* End of Version 3.019 */
BLAKE2B_Hash,
BLAKE2B_HashBuf,
BLAKE2B_MAC_HashBuf,
BLAKE2B_NewContext,
BLAKE2B_DestroyContext,
BLAKE2B_Begin,
BLAKE2B_MAC_Begin,
BLAKE2B_Update,
BLAKE2B_End,
BLAKE2B_FlattenSize,
BLAKE2B_Flatten,
BLAKE2B_Resurrect
/* End of Version 3.020 */
};
const FREEBLVector*
@ -320,8 +336,12 @@ FREEBL_GetVector(void)
return NULL;
}
#endif
/* make sure the Full self tests have been run before continuing */
#ifndef NSS_FIPS_DISABLED
/* In FIPS mode make sure the Full self tests have been run before
* continuing. */
BL_POSTRan(PR_FALSE);
#endif
return &vector;
}

View file

@ -2124,3 +2124,114 @@ EC_GetPointSize(const ECParams *params)
return SECFailure;
return (vector->p_EC_GetPointSize)(params);
}
SECStatus
BLAKE2B_Hash(unsigned char *dest, const char *src)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_Hash)(dest, src);
}
SECStatus
BLAKE2B_HashBuf(unsigned char *output, const unsigned char *input, PRUint32 inlen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_HashBuf)(output, input, inlen);
}
SECStatus
BLAKE2B_MAC_HashBuf(unsigned char *output, const unsigned char *input,
unsigned int inlen, const unsigned char *key,
unsigned int keylen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_MAC_HashBuf)(output, input, inlen, key, keylen);
}
BLAKE2BContext *
BLAKE2B_NewContext(void)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return NULL;
}
return (vector->p_BLAKE2B_NewContext)();
}
void
BLAKE2B_DestroyContext(BLAKE2BContext *BLAKE2BContext, PRBool freeit)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return;
}
(vector->p_BLAKE2B_DestroyContext)(BLAKE2BContext, freeit);
}
SECStatus
BLAKE2B_Begin(BLAKE2BContext *ctx)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_Begin)(ctx);
}
SECStatus
BLAKE2B_MAC_Begin(BLAKE2BContext *ctx, const PRUint8 *key, const size_t keylen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_MAC_Begin)(ctx, key, keylen);
}
SECStatus
BLAKE2B_Update(BLAKE2BContext *ctx, const unsigned char *in, unsigned int inlen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_Update)(ctx, in, inlen);
}
SECStatus
BLAKE2B_End(BLAKE2BContext *ctx, unsigned char *out,
unsigned int *digestLen, size_t maxDigestLen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_End)(ctx, out, digestLen, maxDigestLen);
}
unsigned int
BLAKE2B_FlattenSize(BLAKE2BContext *ctx)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return 0;
}
return (vector->p_BLAKE2B_FlattenSize)(ctx);
}
SECStatus
BLAKE2B_Flatten(BLAKE2BContext *ctx, unsigned char *space)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_BLAKE2B_Flatten)(ctx, space);
}
BLAKE2BContext *
BLAKE2B_Resurrect(unsigned char *space, void *arg)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return NULL;
}
return (vector->p_BLAKE2B_Resurrect)(space, arg);
}

View file

@ -10,7 +10,7 @@
#include "blapi.h"
#define FREEBL_VERSION 0x0313
#define FREEBL_VERSION 0x0314
struct FREEBLVectorStr {
@ -736,6 +736,29 @@ struct FREEBLVectorStr {
/* Version 3.019 came to here */
SECStatus (*p_BLAKE2B_Hash)(unsigned char *dest, const char *src);
SECStatus (*p_BLAKE2B_HashBuf)(unsigned char *output,
const unsigned char *input, PRUint32 inlen);
SECStatus (*p_BLAKE2B_MAC_HashBuf)(unsigned char *output,
const unsigned char *input,
unsigned int inlen,
const unsigned char *key,
unsigned int keylen);
BLAKE2BContext *(*p_BLAKE2B_NewContext)();
void (*p_BLAKE2B_DestroyContext)(BLAKE2BContext *ctx, PRBool freeit);
SECStatus (*p_BLAKE2B_Begin)(BLAKE2BContext *ctx);
SECStatus (*p_BLAKE2B_MAC_Begin)(BLAKE2BContext *ctx, const PRUint8 *key,
const size_t keylen);
SECStatus (*p_BLAKE2B_Update)(BLAKE2BContext *ctx, const unsigned char *in,
unsigned int inlen);
SECStatus (*p_BLAKE2B_End)(BLAKE2BContext *ctx, unsigned char *out,
unsigned int *digestLen, size_t maxDigestLen);
unsigned int (*p_BLAKE2B_FlattenSize)(BLAKE2BContext *ctx);
SECStatus (*p_BLAKE2B_Flatten)(BLAKE2BContext *ctx, unsigned char *space);
BLAKE2BContext *(*p_BLAKE2B_Resurrect)(unsigned char *space, void *arg);
/* Version 3.020 came to here */
/* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */
};

View file

@ -1,10 +1,10 @@
#
#
# 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/.
# NOTE: any ifdefs in this file must be defined on the gmake command line
# (if anywhere). They cannot come from Makefile or config.mk
# (if anywhere). They cannot come from Makefile or config.mk
CORE_DEPTH = ../..
@ -75,7 +75,7 @@ DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \
-DSHLIB_VERSION=\"$(LIBRARY_VERSION)\" \
-DSOFTOKEN_SHLIB_VERSION=\"$(SOFTOKEN_LIBRARY_VERSION)\"
REQUIRES =
REQUIRES =
EXPORTS = \
blapit.h \
@ -86,6 +86,7 @@ EXPORTS = \
PRIVATE_EXPORTS = \
alghmac.h \
blake2b.h \
blapi.h \
chacha20poly1305.h \
hmacct.h \
@ -102,16 +103,13 @@ 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
ifndef NSS_DISABLE_ECC
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
else
ECL_SRCS = $(NULL)
endif
SHA_SRCS = sha_fast.c
MPCPU_SRCS = mpcpucache.c
VERIFIED_SRCS = $(NULL)
CSRCS = \
freeblver.c \
@ -126,6 +124,8 @@ CSRCS = \
alg2268.c \
arcfour.c \
arcfive.c \
crypto_primitives.c \
blake2b.c \
desblapi.c \
des.c \
drbg.c \
@ -153,6 +153,7 @@ CSRCS = \
$(MPI_SRCS) \
$(MPCPU_SRCS) \
$(ECL_SRCS) \
$(VERIFIED_SRCS) \
$(STUBS_SRCS) \
$(LOWHASH_SRCS) \
$(EXTRA_SRCS) \
@ -162,6 +163,7 @@ ALL_CSRCS := $(CSRCS)
ALL_HDRS = \
alghmac.h \
blake2b.h \
blapi.h \
blapit.h \
des.h \
@ -178,12 +180,6 @@ ALL_HDRS = \
$(NULL)
ifdef AES_GEN_TBL
DEFINES += -DRIJNDAEL_GENERATE_TABLES
else
ifdef AES_GEN_TBL_M
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
else
ifdef AES_GEN_VAL
DEFINES += -DRIJNDAEL_GENERATE_VALUES
else
@ -193,5 +189,3 @@ else
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
endif
endif
endif
endif

View file

@ -53,7 +53,7 @@ to change are:
single digit. This is just a printf() format string, so you
can adjust it appropriately.
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
largest value expressible in an mp_digit and an mp_word,
respectively.
@ -345,7 +345,7 @@ returns values of x and y satisfying Bezout's identity. This is used
by mp_invmod() to find modular inverses. However, if you do not need
these values, you will find that mp_gcd() is MUCH more efficient,
since it doesn't need all the intermediate values that mp_xgcd()
requires in order to compute x and y.
requires in order to compute x and y.
The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD
algorithm due to Josef Stein.
@ -361,7 +361,7 @@ mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int
mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int
mp_radix_size(mp, r) - return length of buffer needed by mp_toradix()
mp_raw_size(mp) - return length of buffer needed by mp_toraw()
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
digits
mp_toraw(mp, str) - convert an mp_int to a string of bytes
mp_tovalue(ch, r) - convert ch to its value when taken as
@ -387,7 +387,7 @@ The mp_read_radix() and mp_toradix() functions support bases from 2 to
than this, you will need to write them yourself (that's why mp_div_d()
is provided, after all).
Note: mp_read_radix() will accept as digits either capital or
Note: mp_read_radix() will accept as digits either capital or
---- lower-case letters. However, the current implementation of
mp_toradix() only outputs upper-case letters, when writing
bases betwee 10 and 36. The underlying code supports using
@ -448,14 +448,14 @@ Note: The mpp_random() and mpp_random_size() functions use the C
to change.
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits
in v? If so, let w be the index of
in v? If so, let w be the index of
that digit
mpp_divis_primes(a, np) - is a divisible by any of the first np
primes? If so, set np to the prime
primes? If so, set np to the prime
which divided a.
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
returns MP_YES, otherwise MP_NO.
mpp_pprime(a, nt) - perform nt iterations of the Rabin-
@ -486,7 +486,7 @@ The file 'mpi-config.h' defines several configurable parameters for
the library, which you can adjust to suit your application. At the
time of this writing, the available options are:
MP_IOFUNC - Define true to include the mp_print() function,
MP_IOFUNC - Define true to include the mp_print() function,
which is moderately useful for debugging. This
implicitly includes <stdio.h>.
@ -502,21 +502,14 @@ MP_LOGTAB - If true, the file "logtab.h" is included, which
the library includes <math.h> and uses log(). This
typically forces you to link against math libraries.
MP_MEMSET - If true, use memset() to zero buffers. If you run
into weird alignment related bugs, set this to zero
and an explicit loop will be used.
MP_MEMCPY - If true, use memcpy() to copy buffers. If you run
into weird alignment bugs, set this to zero and an
explicit loop will be used.
MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument
checking macro, ARGCHK(), gets expanded. If this
is set to zero, ARGCHK() expands to nothing; no
checking macro, ARGCHK(), gets expanded. If this
is set to zero, ARGCHK() expands to nothing; no
argument checks are performed. If this is 1, the
ARGCHK() macro expands to code that returns MP_BADARG
or similar at runtime. If it is 2, ARGCHK() expands
to an assert() call that aborts the program on a
or similar at runtime. If it is 2, ARGCHK() expands
to an assert() call that aborts the program on a
bad input.
MP_DEBUG - Turns on debugging output. This is probably not at
@ -528,14 +521,14 @@ MP_DEFPREC - The default precision of a newly-created mp_int, in
the mp_set_prec() function, but this is its initial
value.
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
function will use an alternate algorithm that takes
advantage of the redundant inner product computation
when both multiplicands are identical. Unfortunately,
with some compilers this is actually SLOWER than just
calling mp_mul() with the same argument twice. So
if you set MP_SQUARE to zero, mp_sqr() will be expan-
ded into a call to mp_mul(). This applies to all
ded into a call to mp_mul(). This applies to all
the uses of mp_sqr(), including mp_sqrmod() and the
internal calls to s_mp_sqr() inside mpi.c
@ -568,7 +561,7 @@ CFLAGS=-ansi -pedantic -Wall -O2
If all goes well, the library should compile without warnings using
this combination. You should, of course, make whatever adjustments
you find necessary.
you find necessary.
The MPI library distribution comes with several additional programs
which are intended to demonstrate the use of the library, and provide
@ -580,7 +573,7 @@ directory) for manipulating large numbers. These include:
basecvt.c A radix-conversion program, supporting bases from
2 to 64 inclusive.
bbsrand.c A BBS (quadratic residue) pseudo-random number
bbsrand.c A BBS (quadratic residue) pseudo-random number
generator. The file 'bbsrand.c' is just the driver
for the program; the real code lives in the files
'bbs_rand.h' and 'bbs_rand.c'
@ -626,7 +619,7 @@ Acknowledgements:
----------------
The algorithms used in this library were drawn primarily from Volume
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
"Semi-Numerical Methods". Barrett's algorithm for modular reduction
came from Menezes, Oorschot, and Vanstone's _Handbook of Applied
Cryptography_, Chapter 14.

View file

@ -28,14 +28,6 @@
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
#endif
#ifndef MP_MEMSET
#define MP_MEMSET 1 /* use memset() to zero buffers? */
#endif
#ifndef MP_MEMCPY
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
#endif
#ifndef MP_ARGCHK
/*
0 = no parameter checks

View file

@ -2782,15 +2782,7 @@ s_mp_pad(mp_int *mp, mp_size min)
void
s_mp_setz(mp_digit *dp, mp_size count)
{
#if MP_MEMSET == 0
int ix;
for (ix = 0; ix < count; ix++)
dp[ix] = 0;
#else
memset(dp, 0, count * sizeof(mp_digit));
#endif
} /* end s_mp_setz() */
/* }}} */
@ -2801,14 +2793,7 @@ s_mp_setz(mp_digit *dp, mp_size count)
void
s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count)
{
#if MP_MEMCPY == 0
int ix;
for (ix = 0; ix < count; ix++)
dp[ix] = sp[ix];
#else
memcpy(dp, sp, count * sizeof(mp_digit));
#endif
} /* end s_mp_copy() */
/* }}} */

View file

@ -22,6 +22,7 @@ struct NSSLOWHASHContextStr {
void *hashCtxt;
};
#ifndef NSS_FIPS_DISABLED
static int
nsslow_GetFIPSEnabled(void)
{
@ -40,9 +41,10 @@ nsslow_GetFIPSEnabled(void)
return 0;
if (d != '1')
return 0;
#endif
#endif /* LINUX */
return 1;
}
#endif /* NSS_FIPS_DISABLED */
static NSSLOWInitContext dummyContext = { 0 };
static PRBool post_failed = PR_TRUE;
@ -54,6 +56,7 @@ NSSLOW_Init(void)
(void)FREEBL_InitStubs();
#endif
#ifndef NSS_FIPS_DISABLED
/* make sure the FIPS product is installed if we are trying to
* go into FIPS mode */
if (nsslow_GetFIPSEnabled()) {
@ -63,6 +66,7 @@ NSSLOW_Init(void)
return NULL;
}
}
#endif
post_failed = PR_FALSE;
return &dummyContext;

View file

@ -8,6 +8,8 @@
#ifndef FREEBL_POLY1305_H_
#define FREEBL_POLY1305_H_
#include "stddef.h"
typedef unsigned char poly1305_state[512];
/* Poly1305Init sets up |state| so that it can be used to calculate an

View file

@ -27,16 +27,39 @@
#include "intel-gcm.h"
#endif /* INTEL_GCM */
/* Forward declarations */
void rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
unsigned int Nk);
void rijndael_native_encryptBlock(AESContext *cx,
unsigned char *output,
const unsigned char *input);
/* Stub definitions for the above rijndael_native_* functions, which
* shouldn't be used unless NSS_X86_OR_X64 is defined */
#ifndef NSS_X86_OR_X64
void
rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
unsigned int Nk)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_Assert(0);
}
void
rijndael_native_encryptBlock(AESContext *cx,
unsigned char *output,
const unsigned char *input)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_Assert(0);
}
#endif /* NSS_X86_OR_X64 */
/*
* There are currently five ways to build this code, varying in performance
* There are currently three ways to build this code, varying in performance
* and code size.
*
* RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab
* RIJNDAEL_GENERATE_TABLES Generate tables on first
* encryption/decryption, then store them;
* use the function gfm
* RIJNDAEL_GENERATE_TABLES_MACRO Same as above, but use macros to do
* the generation
* RIJNDAEL_GENERATE_VALUES Do not store tables, generate the table
* values "on-the-fly", using gfm
* RIJNDAEL_GENERATE_VALUES_MACRO Same as above, but use macros
@ -108,8 +131,7 @@
((a & 0x80) ? ((a << 1) ^ 0x1b) : (a << 1))
/* Choose GFM method (macros or function) */
#if defined(RIJNDAEL_GENERATE_TABLES_MACRO) || \
defined(RIJNDAEL_GENERATE_VALUES_MACRO)
#if defined(RIJNDAEL_GENERATE_VALUES_MACRO)
/*
* Galois field GF(2**8) multipliers, in macro form
@ -133,7 +155,7 @@
#define GFM0E(a) \
(GFM02(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0E = a * (02 + 04 + 08) */
#else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_VALUES */
#else /* RIJNDAEL_GENERATE_VALUES */
/* GF_MULTIPLY
*
@ -244,7 +266,7 @@ gen_TInvXi(PRUint8 tx, PRUint8 i)
#define IMXC1(b) G_IMXC1(b)
#define IMXC2(b) G_IMXC2(b)
#define IMXC3(b) G_IMXC3(b)
#elif defined(RIJNDAEL_GENERATE_VALUES_MACRO)
#else /* RIJNDAEL_GENERATE_VALUES_MACRO */
/* generate values for the tables with macros */
#define T0(i) G_T0(i)
#define T1(i) G_T1(i)
@ -258,84 +280,10 @@ gen_TInvXi(PRUint8 tx, PRUint8 i)
#define IMXC1(b) G_IMXC1(b)
#define IMXC2(b) G_IMXC2(b)
#define IMXC3(b) G_IMXC3(b)
#else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_TABLES_MACRO */
/* Generate T and T**-1 table values and store, then index */
/* The inverse mix column tables are still generated */
#define T0(i) rijndaelTables->T0[i]
#define T1(i) rijndaelTables->T1[i]
#define T2(i) rijndaelTables->T2[i]
#define T3(i) rijndaelTables->T3[i]
#define TInv0(i) rijndaelTables->TInv0[i]
#define TInv1(i) rijndaelTables->TInv1[i]
#define TInv2(i) rijndaelTables->TInv2[i]
#define TInv3(i) rijndaelTables->TInv3[i]
#define IMXC0(b) G_IMXC0(b)
#define IMXC1(b) G_IMXC1(b)
#define IMXC2(b) G_IMXC2(b)
#define IMXC3(b) G_IMXC3(b)
#endif /* choose T-table indexing method */
#endif /* not RIJNDAEL_INCLUDE_TABLES */
#if defined(RIJNDAEL_GENERATE_TABLES) || \
defined(RIJNDAEL_GENERATE_TABLES_MACRO)
/* Code to generate and store the tables */
struct rijndael_tables_str {
PRUint32 T0[256];
PRUint32 T1[256];
PRUint32 T2[256];
PRUint32 T3[256];
PRUint32 TInv0[256];
PRUint32 TInv1[256];
PRUint32 TInv2[256];
PRUint32 TInv3[256];
};
static struct rijndael_tables_str *rijndaelTables = NULL;
static PRCallOnceType coRTInit = { 0, 0, 0 };
static PRStatus
init_rijndael_tables(void)
{
PRUint32 i;
PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
struct rijndael_tables_str *rts;
rts = (struct rijndael_tables_str *)
PORT_Alloc(sizeof(struct rijndael_tables_str));
if (!rts)
return PR_FAILURE;
for (i = 0; i < 256; i++) {
/* The forward values */
si01 = SBOX(i);
si02 = XTIME(si01);
si03 = si02 ^ si01;
rts->T0[i] = WORD4(si02, si01, si01, si03);
rts->T1[i] = WORD4(si03, si02, si01, si01);
rts->T2[i] = WORD4(si01, si03, si02, si01);
rts->T3[i] = WORD4(si01, si01, si03, si02);
/* The inverse values */
si01 = SINV(i);
si02 = XTIME(si01);
si04 = XTIME(si02);
si08 = XTIME(si04);
si03 = si02 ^ si01;
si09 = si08 ^ si01;
si0B = si08 ^ si03;
si0D = si09 ^ si04;
si0E = si08 ^ si04 ^ si02;
rts->TInv0[i] = WORD4(si0E, si09, si0D, si0B);
rts->TInv1[i] = WORD4(si0B, si0E, si09, si0D);
rts->TInv2[i] = WORD4(si0D, si0B, si0E, si09);
rts->TInv3[i] = WORD4(si09, si0D, si0B, si0E);
}
/* wait until all the values are in to set */
rijndaelTables = rts;
return PR_SUCCESS;
}
#endif /* code to generate tables */
/**************************************************************************
*
* Stuff related to the Rijndael key schedule
@ -389,162 +337,6 @@ rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int N
}
}
#if defined(NSS_X86_OR_X64)
#define EXPAND_KEY128(k, rcon, res) \
tmp_key = _mm_aeskeygenassist_si128(k, rcon); \
tmp_key = _mm_shuffle_epi32(tmp_key, 0xFF); \
tmp = _mm_xor_si128(k, _mm_slli_si128(k, 4)); \
tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
res = _mm_xor_si128(tmp, tmp_key)
static void
native_key_expansion128(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
EXPAND_KEY128(keySchedule[0], 0x01, keySchedule[1]);
EXPAND_KEY128(keySchedule[1], 0x02, keySchedule[2]);
EXPAND_KEY128(keySchedule[2], 0x04, keySchedule[3]);
EXPAND_KEY128(keySchedule[3], 0x08, keySchedule[4]);
EXPAND_KEY128(keySchedule[4], 0x10, keySchedule[5]);
EXPAND_KEY128(keySchedule[5], 0x20, keySchedule[6]);
EXPAND_KEY128(keySchedule[6], 0x40, keySchedule[7]);
EXPAND_KEY128(keySchedule[7], 0x80, keySchedule[8]);
EXPAND_KEY128(keySchedule[8], 0x1B, keySchedule[9]);
EXPAND_KEY128(keySchedule[9], 0x36, keySchedule[10]);
}
#define EXPAND_KEY192_PART1(res, k0, kt, rcon) \
tmp2 = _mm_slli_si128(k0, 4); \
tmp1 = _mm_xor_si128(k0, tmp2); \
tmp2 = _mm_slli_si128(tmp2, 4); \
tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
tmp2 = _mm_aeskeygenassist_si128(kt, rcon); \
res = _mm_xor_si128(tmp1, _mm_shuffle_epi32(tmp2, 0x55))
#define EXPAND_KEY192_PART2(res, k1, k2) \
tmp2 = _mm_xor_si128(k1, _mm_slli_si128(k1, 4)); \
res = _mm_xor_si128(tmp2, _mm_shuffle_epi32(k2, 0xFF))
#define EXPAND_KEY192(k0, res1, res2, res3, carry, rcon1, rcon2) \
EXPAND_KEY192_PART1(tmp3, k0, res1, rcon1); \
EXPAND_KEY192_PART2(carry, res1, tmp3); \
res1 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(res1), \
_mm_castsi128_pd(tmp3), 0)); \
res2 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(tmp3), \
_mm_castsi128_pd(carry), 1)); \
EXPAND_KEY192_PART1(res3, tmp3, carry, rcon2)
static void
native_key_expansion192(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
pre_align __m128i tmp3 post_align;
pre_align __m128i carry post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
EXPAND_KEY192(keySchedule[0], keySchedule[1], keySchedule[2],
keySchedule[3], carry, 0x1, 0x2);
EXPAND_KEY192_PART2(keySchedule[4], carry, keySchedule[3]);
EXPAND_KEY192(keySchedule[3], keySchedule[4], keySchedule[5],
keySchedule[6], carry, 0x4, 0x8);
EXPAND_KEY192_PART2(keySchedule[7], carry, keySchedule[6]);
EXPAND_KEY192(keySchedule[6], keySchedule[7], keySchedule[8],
keySchedule[9], carry, 0x10, 0x20);
EXPAND_KEY192_PART2(keySchedule[10], carry, keySchedule[9]);
EXPAND_KEY192(keySchedule[9], keySchedule[10], keySchedule[11],
keySchedule[12], carry, 0x40, 0x80);
}
#define EXPAND_KEY256_PART(res, rconx, k1x, k2x, X) \
tmp_key = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(k2x, rconx), X); \
tmp2 = _mm_slli_si128(k1x, 4); \
tmp1 = _mm_xor_si128(k1x, tmp2); \
tmp2 = _mm_slli_si128(tmp2, 4); \
tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
res = _mm_xor_si128(tmp1, tmp_key);
#define EXPAND_KEY256(res1, res2, k1, k2, rcon) \
EXPAND_KEY256_PART(res1, rcon, k1, k2, 0xFF); \
EXPAND_KEY256_PART(res2, 0x00, k2, res1, 0xAA)
static void
native_key_expansion256(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
EXPAND_KEY256(keySchedule[2], keySchedule[3], keySchedule[0],
keySchedule[1], 0x01);
EXPAND_KEY256(keySchedule[4], keySchedule[5], keySchedule[2],
keySchedule[3], 0x02);
EXPAND_KEY256(keySchedule[6], keySchedule[7], keySchedule[4],
keySchedule[5], 0x04);
EXPAND_KEY256(keySchedule[8], keySchedule[9], keySchedule[6],
keySchedule[7], 0x08);
EXPAND_KEY256(keySchedule[10], keySchedule[11], keySchedule[8],
keySchedule[9], 0x10);
EXPAND_KEY256(keySchedule[12], keySchedule[13], keySchedule[10],
keySchedule[11], 0x20);
EXPAND_KEY256_PART(keySchedule[14], 0x40, keySchedule[12],
keySchedule[13], 0xFF);
}
#endif /* NSS_X86_OR_X64 */
/*
* AES key expansion using aes-ni instructions.
*/
static void
native_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
{
#ifdef NSS_X86_OR_X64
switch (Nk) {
case 4:
native_key_expansion128(cx, key);
return;
case 6:
native_key_expansion192(cx, key);
return;
case 8:
native_key_expansion256(cx, key);
return;
default:
/* This shouldn't happen. */
PORT_Assert(0);
}
#else
PORT_Assert(0);
#endif /* NSS_X86_OR_X64 */
}
static void
native_encryptBlock(AESContext *cx,
unsigned char *output,
const unsigned char *input)
{
#ifdef NSS_X86_OR_X64
int i;
pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
m = _mm_xor_si128(m, cx->keySchedule[0]);
for (i = 1; i < cx->Nr; ++i) {
m = _mm_aesenc_si128(m, cx->keySchedule[i]);
}
m = _mm_aesenclast_si128(m, cx->keySchedule[cx->Nr]);
_mm_storeu_si128((__m128i *)output, m);
#else
PORT_Assert(0);
#endif /* NSS_X86_OR_X64 */
}
/* rijndael_key_expansion
*
* Generate the expanded key from the key input by the user.
@ -910,7 +702,7 @@ rijndael_encryptECB(AESContext *cx, unsigned char *output,
if (aesni_support()) {
/* Use hardware acceleration for normal AES parameters. */
encryptor = &native_encryptBlock;
encryptor = &rijndael_native_encryptBlock;
} else {
encryptor = &rijndael_encryptBlock128;
}
@ -1017,14 +809,7 @@ rijndael_decryptCBC(AESContext *cx, unsigned char *output,
AESContext *
AES_AllocateContext(void)
{
/* aligned_alloc is C11 so we have to do it the old way. */
AESContext *ctx = PORT_ZAlloc(sizeof(AESContext) + 15);
if (ctx == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
}
ctx->mem = ctx;
return (AESContext *)(((uintptr_t)ctx + 15) & ~(uintptr_t)0x0F);
return PORT_ZNewAligned(AESContext, 16, mem);
}
/*
@ -1107,22 +892,13 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
} else
#endif
{
#if defined(RIJNDAEL_GENERATE_TABLES) || \
defined(RIJNDAEL_GENERATE_TABLES_MACRO)
if (rijndaelTables == NULL) {
if (PR_CallOnce(&coRTInit, init_rijndael_tables) != PR_SUCCESS) {
return SECFailure;
}
}
#endif
/* Generate expanded key */
if (encrypt) {
if (use_hw_aes && (cx->mode == NSS_AES_GCM || cx->mode == NSS_AES ||
cx->mode == NSS_AES_CTR)) {
PORT_Assert(keysize == 16 || keysize == 24 || keysize == 32);
/* Prepare hardware key for normal AES parameters. */
native_key_expansion(cx, key, Nk);
rijndael_native_key_expansion(cx, key, Nk);
} else {
rijndael_key_expansion(cx, key, Nk);
}

View file

@ -8,8 +8,22 @@
#include "blapii.h"
#include <stdint.h>
#ifdef NSS_X86_OR_X64
#include <wmmintrin.h> /* aes-ni */
#if defined(NSS_X86_OR_X64)
/* GCC <= 4.8 doesn't support including emmintrin.h without enabling SSE2 */
#if !defined(__clang__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && \
(__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
#pragma GCC push_options
#pragma GCC target("sse2")
#undef NSS_DISABLE_SSE2
#define NSS_DISABLE_SSE2 1
#endif /* GCC <= 4.8 */
#include <emmintrin.h> /* __m128i */
#ifdef NSS_DISABLE_SSE2
#undef NSS_DISABLE_SSE2
#pragma GCC pop_options
#endif /* NSS_DISABLE_SSE2 */
#endif
typedef void AESBlockFunc(AESContext *cx,

View file

@ -276,7 +276,10 @@ RSAPrivateKey *
RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
{
unsigned int primeLen;
mp_int p, q, e, d;
mp_int p = { 0, 0, 0, NULL };
mp_int q = { 0, 0, 0, NULL };
mp_int e = { 0, 0, 0, NULL };
mp_int d = { 0, 0, 0, NULL };
int kiter;
int max_attempts;
mp_err err = MP_OKAY;
@ -290,34 +293,46 @@ RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
/* 1. Allocate arena & key */
/* 1. Set the public exponent and check if it's uneven and greater than 2.*/
MP_DIGITS(&e) = 0;
CHECK_MPI_OK(mp_init(&e));
SECITEM_TO_MPINT(*publicExponent, &e);
if (mp_iseven(&e) || !(mp_cmp_d(&e, 2) > 0)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto cleanup;
}
#ifndef NSS_FIPS_DISABLED
/* Check that the exponent is not smaller than 65537 */
if (mp_cmp_d(&e, 0x10001) < 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto cleanup;
}
#endif
/* 2. Allocate arena & key */
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
if (!arena) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
goto cleanup;
}
key = PORT_ArenaZNew(arena, RSAPrivateKey);
if (!key) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
PORT_FreeArena(arena, PR_TRUE);
return NULL;
goto cleanup;
}
key->arena = arena;
/* length of primes p and q (in bytes) */
primeLen = keySizeInBits / (2 * PR_BITS_PER_BYTE);
MP_DIGITS(&p) = 0;
MP_DIGITS(&q) = 0;
MP_DIGITS(&e) = 0;
MP_DIGITS(&d) = 0;
CHECK_MPI_OK(mp_init(&p));
CHECK_MPI_OK(mp_init(&q));
CHECK_MPI_OK(mp_init(&e));
CHECK_MPI_OK(mp_init(&d));
/* 2. Set the version number (PKCS1 v1.5 says it should be zero) */
/* 3. Set the version number (PKCS1 v1.5 says it should be zero) */
SECITEM_AllocItem(arena, &key->version, 1);
key->version.data[0] = 0;
/* 3. Set the public exponent */
SECITEM_TO_MPINT(*publicExponent, &e);
kiter = 0;
max_attempts = 5 * (keySizeInBits / 2); /* FIPS 186-4 B.3.3 steps 4.7 and 5.8 */
do {

View file

@ -19,6 +19,7 @@
#include "secport.h" /* for PORT_XXX */
#include "blapi.h"
#include "sha256.h" /* for struct SHA256ContextStr */
#include "crypto_primitives.h"
/* ============= Common constants and defines ======================= */
@ -648,15 +649,6 @@ SHA224_Clone(SHA224Context *dest, SHA224Context *src)
/* common #defines for SHA512 and SHA384 */
#if defined(HAVE_LONG_LONG)
#if defined(_MSC_VER)
#pragma intrinsic(_rotr64, _rotl64)
#define ROTR64(x, n) _rotr64(x, n)
#define ROTL64(x, n) _rotl64(x, n)
#else
#define ROTR64(x, n) ((x >> n) | (x << (64 - n)))
#define ROTL64(x, n) ((x << n) | (x >> (64 - n)))
#endif
#define S0(x) (ROTR64(x, 28) ^ ROTR64(x, 34) ^ ROTR64(x, 39))
#define S1(x) (ROTR64(x, 14) ^ ROTR64(x, 18) ^ ROTR64(x, 41))
#define s0(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ SHR(x, 7))
@ -670,36 +662,7 @@ SHA224_Clone(SHA224Context *dest, SHA224Context *src)
#define ULLC(hi, lo) 0x##hi##lo##ULL
#endif
#if defined(IS_LITTLE_ENDIAN)
#if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64)
#define SHA_HTONLL(x) _byteswap_uint64(x)
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
static __inline__ PRUint64
swap8b(PRUint64 value)
{
__asm__("bswapq %0"
: "+r"(value));
return (value);
}
#define SHA_HTONLL(x) swap8b(x)
#else
#define SHA_MASK16 ULLC(0000FFFF, 0000FFFF)
#define SHA_MASK8 ULLC(00FF00FF, 00FF00FF)
static PRUint64
swap8b(PRUint64 x)
{
PRUint64 t1 = x;
t1 = ((t1 & SHA_MASK8) << 8) | ((t1 >> 8) & SHA_MASK8);
t1 = ((t1 & SHA_MASK16) << 16) | ((t1 >> 16) & SHA_MASK16);
return (t1 >> 32) | (t1 << 32);
}
#define SHA_HTONLL(x) swap8b(x)
#endif
#define BYTESWAP8(x) x = SHA_HTONLL(x)
#endif /* defined(IS_LITTLE_ENDIAN) */
#define BYTESWAP8(x) x = FREEBL_HTONLL(x)
#else /* no long long */
@ -708,8 +671,8 @@ swap8b(PRUint64 x)
{ \
0x##lo##U, 0x##hi##U \
}
#define SHA_HTONLL(x) (BYTESWAP4(x.lo), BYTESWAP4(x.hi), \
x.hi ^= x.lo ^= x.hi ^= x.lo, x)
#define FREEBL_HTONLL(x) (BYTESWAP4(x.lo), BYTESWAP4(x.hi), \
x.hi ^= x.lo ^= x.hi ^= x.lo, x)
#define BYTESWAP8(x) \
do { \
PRUint32 tmp; \

View file

@ -19,6 +19,8 @@
#include "pqg.h"
#include "blapii.h"
#ifndef NSS_FIPS_DISABLED
/*
* Most modern version of Linux support a speed optimization scheme where an
* application called prelink modifies programs and shared libraries to quickly
@ -537,3 +539,23 @@ BLAPI_VerifySelf(const char *name)
}
return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE);
}
#else /* NSS_FIPS_DISABLED */
PRBool
BLAPI_SHVerifyFile(const char *shName)
{
return PR_FALSE;
}
PRBool
BLAPI_SHVerify(const char *name, PRFuncPtr addr)
{
return PR_FALSE;
}
PRBool
BLAPI_VerifySelf(const char *name)
{
return PR_FALSE;
}
#endif /* NSS_FIPS_DISABLED */

View file

@ -38,6 +38,11 @@
#include <blapi.h>
#include <private/pprio.h>
/* Android API < 21 doesn't define RTLD_NOLOAD */
#ifndef RTLD_NOLOAD
#define RTLD_NOLOAD 0
#endif
#define FREEBL_NO_WEAK 1
#define WEAK __attribute__((weak))
@ -136,6 +141,11 @@ STUB_DECLARE(int, PORT_GetError_Util, (void));
STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
STUB_DECLARE(void, PORT_SetError_Util, (int value));
STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment,
void **mem));
STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes,
size_t alignment,
size_t offset));
STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));
STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
@ -174,11 +184,14 @@ STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
STUB_DECLARE(SECOidTag, SECOID_FindOIDTag_Util, (const SECItem *oid));
STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
STUB_DECLARE(unsigned int, NSS_SecureMemcmpZero, (const void *mem, size_t n));
#define PORT_ZNew_stub(type) (type *)PORT_ZAlloc_stub(sizeof(type))
#define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
#define PORT_ZNewArray_stub(type, num) \
(type *)PORT_ZAlloc_stub(sizeof(type) * (num))
#define PORT_ZNewAligned_stub(type, alignment, mem) \
(type *)PORT_ZAllocAlignedOffset_stub(sizeof(type), alignment, offsetof(type, mem))
/*
* NOTE: in order to support hashing only the memory allocation stubs,
@ -214,6 +227,52 @@ PORT_ZAlloc_stub(size_t len)
return ptr;
}
/* aligned_alloc is C11. This is an alternative to get aligned memory. */
extern void *
PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem)
{
STUB_SAFE_CALL3(PORT_ZAllocAligned_Util, bytes, alignment, mem);
/* This only works if alignement is a power of 2. */
if ((alignment == 0) || (alignment & (alignment - 1))) {
return NULL;
}
size_t x = alignment - 1;
size_t len = (bytes ? bytes : 1) + x;
if (!mem) {
return NULL;
}
/* Always allocate a non-zero amount of bytes */
*mem = malloc(len);
if (!*mem) {
return NULL;
}
memset(*mem, 0, len);
return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
}
extern void *
PORT_ZAllocAlignedOffset_stub(size_t size, size_t alignment, size_t offset)
{
STUB_SAFE_CALL3(PORT_ZAllocAlignedOffset_Util, size, alignment, offset);
if (offset > size) {
return NULL;
}
void *mem = NULL;
void *v = PORT_ZAllocAligned_stub(size, alignment, &mem);
if (!v) {
return NULL;
}
*((void **)((uintptr_t)v + offset)) = mem;
return v;
}
extern void
PORT_ZFree_stub(void *ptr, size_t len)
{
@ -590,6 +649,13 @@ NSS_SecureMemcmp_stub(const void *a, const void *b, size_t n)
abort();
}
extern unsigned int
NSS_SecureMemcmpZero_stub(const void *mem, size_t n)
{
STUB_SAFE_CALL2(NSS_SecureMemcmpZero, mem, n);
abort();
}
#ifdef FREEBL_NO_WEAK
static const char *nsprLibName = SHLIB_PREFIX "nspr4." SHLIB_SUFFIX;
@ -642,6 +708,7 @@ freebl_InitNSSUtil(void *lib)
STUB_FETCH_FUNCTION(SECITEM_ZfreeItem_Util);
STUB_FETCH_FUNCTION(SECOID_FindOIDTag_Util);
STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
STUB_FETCH_FUNCTION(NSS_SecureMemcmpZero);
return SECSuccess;
}

View file

@ -30,6 +30,8 @@
#define PORT_SetError PORT_SetError_stub
#define PORT_ZAlloc PORT_ZAlloc_stub
#define PORT_ZFree PORT_ZFree_stub
#define PORT_ZAllocAligned PORT_ZAllocAligned_stub
#define PORT_ZAllocAlignedOffset PORT_ZAllocAlignedOffset_stub
#define SECITEM_AllocItem SECITEM_AllocItem_stub
#define SECITEM_CompareItem SECITEM_CompareItem_stub
@ -38,6 +40,7 @@
#define SECITEM_ZfreeItem SECITEM_ZfreeItem_stub
#define SECOID_FindOIDTag SECOID_FindOIDTag_stub
#define NSS_SecureMemcmp NSS_SecureMemcmp_stub
#define NSS_SecureMemcmpZero NSS_SecureMemcmpZero_stub
#define PR_Assert PR_Assert_stub
#define PR_Access PR_Access_stub

View file

@ -0,0 +1,255 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file was auto-generated by KreMLin! */
#include "FStar.h"
static uint64_t
FStar_UInt128_constant_time_carry(uint64_t a, uint64_t b)
{
return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (uint32_t)63U;
}
static uint64_t
FStar_UInt128_carry(uint64_t a, uint64_t b)
{
return FStar_UInt128_constant_time_carry(a, b);
}
FStar_UInt128_uint128
FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low + b.low,
.high = a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) });
}
FStar_UInt128_uint128
FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low + b.low,
.high = a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) });
}
FStar_UInt128_uint128
FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low - b.low,
.high = a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) });
}
static FStar_UInt128_uint128
FStar_UInt128_sub_mod_impl(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low - b.low,
.high = a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) });
}
FStar_UInt128_uint128
FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return FStar_UInt128_sub_mod_impl(a, b);
}
FStar_UInt128_uint128
FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return ((FStar_UInt128_uint128){.low = a.low & b.low, .high = a.high & b.high });
}
FStar_UInt128_uint128
FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return ((FStar_UInt128_uint128){.low = a.low ^ b.low, .high = a.high ^ b.high });
}
FStar_UInt128_uint128
FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return ((FStar_UInt128_uint128){.low = a.low | b.low, .high = a.high | b.high });
}
FStar_UInt128_uint128
FStar_UInt128_lognot(FStar_UInt128_uint128 a)
{
return ((FStar_UInt128_uint128){.low = ~a.low, .high = ~a.high });
}
static uint32_t FStar_UInt128_u32_64 = (uint32_t)64U;
static uint64_t
FStar_UInt128_add_u64_shift_left(uint64_t hi, uint64_t lo, uint32_t s)
{
return (hi << s) + (lo >> (FStar_UInt128_u32_64 - s));
}
static uint64_t
FStar_UInt128_add_u64_shift_left_respec(uint64_t hi, uint64_t lo, uint32_t s)
{
return FStar_UInt128_add_u64_shift_left(hi, lo, s);
}
static FStar_UInt128_uint128
FStar_UInt128_shift_left_small(FStar_UInt128_uint128 a, uint32_t s)
{
if (s == (uint32_t)0U)
return a;
else
return (
(FStar_UInt128_uint128){
.low = a.low << s,
.high = FStar_UInt128_add_u64_shift_left_respec(a.high, a.low, s) });
}
static FStar_UInt128_uint128
FStar_UInt128_shift_left_large(FStar_UInt128_uint128 a, uint32_t s)
{
return ((FStar_UInt128_uint128){.low = (uint64_t)0U, .high = a.low << (s - FStar_UInt128_u32_64) });
}
FStar_UInt128_uint128
FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s)
{
if (s < FStar_UInt128_u32_64)
return FStar_UInt128_shift_left_small(a, s);
else
return FStar_UInt128_shift_left_large(a, s);
}
static uint64_t
FStar_UInt128_add_u64_shift_right(uint64_t hi, uint64_t lo, uint32_t s)
{
return (lo >> s) + (hi << (FStar_UInt128_u32_64 - s));
}
static uint64_t
FStar_UInt128_add_u64_shift_right_respec(uint64_t hi, uint64_t lo, uint32_t s)
{
return FStar_UInt128_add_u64_shift_right(hi, lo, s);
}
static FStar_UInt128_uint128
FStar_UInt128_shift_right_small(FStar_UInt128_uint128 a, uint32_t s)
{
if (s == (uint32_t)0U)
return a;
else
return (
(FStar_UInt128_uint128){
.low = FStar_UInt128_add_u64_shift_right_respec(a.high, a.low, s),
.high = a.high >> s });
}
static FStar_UInt128_uint128
FStar_UInt128_shift_right_large(FStar_UInt128_uint128 a, uint32_t s)
{
return ((FStar_UInt128_uint128){.low = a.high >> (s - FStar_UInt128_u32_64), .high = (uint64_t)0U });
}
FStar_UInt128_uint128
FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s)
{
if (s < FStar_UInt128_u32_64)
return FStar_UInt128_shift_right_small(a, s);
else
return FStar_UInt128_shift_right_large(a, s);
}
FStar_UInt128_uint128
FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = FStar_UInt64_eq_mask(a.low, b.low) & FStar_UInt64_eq_mask(a.high, b.high),
.high = FStar_UInt64_eq_mask(a.low, b.low) & FStar_UInt64_eq_mask(a.high, b.high) });
}
FStar_UInt128_uint128
FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)),
.high = (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)) });
}
FStar_UInt128_uint128
FStar_UInt128_uint64_to_uint128(uint64_t a)
{
return ((FStar_UInt128_uint128){.low = a, .high = (uint64_t)0U });
}
uint64_t
FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a)
{
return a.low;
}
static uint64_t FStar_UInt128_u64_l32_mask = (uint64_t)0xffffffffU;
static uint64_t
FStar_UInt128_u64_mod_32(uint64_t a)
{
return a & FStar_UInt128_u64_l32_mask;
}
static uint32_t FStar_UInt128_u32_32 = (uint32_t)32U;
static K___uint64_t_uint64_t_uint64_t_uint64_t
FStar_UInt128_mul_wide_impl_t_(uint64_t x, uint64_t y)
{
return (
(K___uint64_t_uint64_t_uint64_t_uint64_t){
.fst = FStar_UInt128_u64_mod_32(x),
.snd = FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y)),
.thd = x >> FStar_UInt128_u32_32,
.f3 = (x >> FStar_UInt128_u32_32) * FStar_UInt128_u64_mod_32(y) + (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32) });
}
static uint64_t
FStar_UInt128_u32_combine_(uint64_t hi, uint64_t lo)
{
return lo + (hi << FStar_UInt128_u32_32);
}
static FStar_UInt128_uint128
FStar_UInt128_mul_wide_impl(uint64_t x, uint64_t y)
{
K___uint64_t_uint64_t_uint64_t_uint64_t scrut = FStar_UInt128_mul_wide_impl_t_(x, y);
uint64_t u1 = scrut.fst;
uint64_t w3 = scrut.snd;
uint64_t x_ = scrut.thd;
uint64_t t_ = scrut.f3;
return (
(FStar_UInt128_uint128){
.low = FStar_UInt128_u32_combine_(u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_),
w3),
.high = x_ * (y >> FStar_UInt128_u32_32) + (t_ >> FStar_UInt128_u32_32) +
((u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_)) >> FStar_UInt128_u32_32) });
}
FStar_UInt128_uint128
FStar_UInt128_mul_wide(uint64_t x, uint64_t y)
{
return FStar_UInt128_mul_wide_impl(x, y);
}

View file

@ -0,0 +1,69 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file was auto-generated by KreMLin! */
#ifndef __FStar_H
#define __FStar_H
#include "kremlib_base.h"
typedef struct
{
uint64_t low;
uint64_t high;
} FStar_UInt128_uint128;
typedef FStar_UInt128_uint128 FStar_UInt128_t;
extern void FStar_UInt128_constant_time_carry_ok(uint64_t x0, uint64_t x1);
FStar_UInt128_uint128 FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a);
FStar_UInt128_uint128 FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s);
FStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s);
FStar_UInt128_uint128 FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a);
uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a);
typedef struct
{
uint64_t fst;
uint64_t snd;
uint64_t thd;
uint64_t f3;
} K___uint64_t_uint64_t_uint64_t_uint64_t;
FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y);
#endif

View file

@ -0,0 +1,270 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Hacl_Chacha20.h"
static void
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(uint32_t *output, uint8_t *input, uint32_t len)
{
for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
uint8_t *x0 = input + (uint32_t)4U * i;
uint32_t inputi = load32_le(x0);
output[i] = inputi;
}
}
static void
Hacl_Lib_LoadStore32_uint32s_to_le_bytes(uint8_t *output, uint32_t *input, uint32_t len)
{
for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
uint32_t hd1 = input[i];
uint8_t *x0 = output + (uint32_t)4U * i;
store32_le(x0, hd1);
}
}
inline static uint32_t
Hacl_Impl_Chacha20_rotate_left(uint32_t a, uint32_t s)
{
return a << s | a >> ((uint32_t)32U - s);
}
inline static void
Hacl_Impl_Chacha20_quarter_round(uint32_t *st, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
uint32_t sa = st[a];
uint32_t sb0 = st[b];
st[a] = sa + sb0;
uint32_t sd = st[d];
uint32_t sa10 = st[a];
uint32_t sda = sd ^ sa10;
st[d] = Hacl_Impl_Chacha20_rotate_left(sda, (uint32_t)16U);
uint32_t sa0 = st[c];
uint32_t sb1 = st[d];
st[c] = sa0 + sb1;
uint32_t sd0 = st[b];
uint32_t sa11 = st[c];
uint32_t sda0 = sd0 ^ sa11;
st[b] = Hacl_Impl_Chacha20_rotate_left(sda0, (uint32_t)12U);
uint32_t sa2 = st[a];
uint32_t sb2 = st[b];
st[a] = sa2 + sb2;
uint32_t sd1 = st[d];
uint32_t sa12 = st[a];
uint32_t sda1 = sd1 ^ sa12;
st[d] = Hacl_Impl_Chacha20_rotate_left(sda1, (uint32_t)8U);
uint32_t sa3 = st[c];
uint32_t sb = st[d];
st[c] = sa3 + sb;
uint32_t sd2 = st[b];
uint32_t sa1 = st[c];
uint32_t sda2 = sd2 ^ sa1;
st[b] = Hacl_Impl_Chacha20_rotate_left(sda2, (uint32_t)7U);
}
inline static void
Hacl_Impl_Chacha20_double_round(uint32_t *st)
{
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)0U, (uint32_t)4U, (uint32_t)8U, (uint32_t)12U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)1U, (uint32_t)5U, (uint32_t)9U, (uint32_t)13U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)2U, (uint32_t)6U, (uint32_t)10U, (uint32_t)14U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)3U, (uint32_t)7U, (uint32_t)11U, (uint32_t)15U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)0U, (uint32_t)5U, (uint32_t)10U, (uint32_t)15U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)1U, (uint32_t)6U, (uint32_t)11U, (uint32_t)12U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)2U, (uint32_t)7U, (uint32_t)8U, (uint32_t)13U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)3U, (uint32_t)4U, (uint32_t)9U, (uint32_t)14U);
}
inline static void
Hacl_Impl_Chacha20_rounds(uint32_t *st)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)10U; i = i + (uint32_t)1U)
Hacl_Impl_Chacha20_double_round(st);
}
inline static void
Hacl_Impl_Chacha20_sum_states(uint32_t *st, uint32_t *st_)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)16U; i = i + (uint32_t)1U) {
uint32_t xi = st[i];
uint32_t yi = st_[i];
st[i] = xi + yi;
}
}
inline static void
Hacl_Impl_Chacha20_copy_state(uint32_t *st, uint32_t *st_)
{
memcpy(st, st_, (uint32_t)16U * sizeof st_[0U]);
}
inline static void
Hacl_Impl_Chacha20_chacha20_core(uint32_t *k, uint32_t *st, uint32_t ctr)
{
st[12U] = ctr;
Hacl_Impl_Chacha20_copy_state(k, st);
Hacl_Impl_Chacha20_rounds(k);
Hacl_Impl_Chacha20_sum_states(k, st);
}
inline static void
Hacl_Impl_Chacha20_chacha20_block(uint8_t *stream_block, uint32_t *st, uint32_t ctr)
{
uint32_t st_[16U] = { 0U };
Hacl_Impl_Chacha20_chacha20_core(st_, st, ctr);
Hacl_Lib_LoadStore32_uint32s_to_le_bytes(stream_block, st_, (uint32_t)16U);
}
inline static void
Hacl_Impl_Chacha20_init(uint32_t *st, uint8_t *k, uint8_t *n1)
{
uint32_t *stcst = st;
uint32_t *stk = st + (uint32_t)4U;
uint32_t *stc = st + (uint32_t)12U;
uint32_t *stn = st + (uint32_t)13U;
stcst[0U] = (uint32_t)0x61707865U;
stcst[1U] = (uint32_t)0x3320646eU;
stcst[2U] = (uint32_t)0x79622d32U;
stcst[3U] = (uint32_t)0x6b206574U;
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stk, k, (uint32_t)8U);
stc[0U] = (uint32_t)0U;
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stn, n1, (uint32_t)3U);
}
static void
Hacl_Impl_Chacha20_update(uint8_t *output, uint8_t *plain, uint32_t *st, uint32_t ctr)
{
uint32_t b[48U] = { 0U };
uint32_t *k = b;
uint32_t *ib = b + (uint32_t)16U;
uint32_t *ob = b + (uint32_t)32U;
Hacl_Impl_Chacha20_chacha20_core(k, st, ctr);
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(ib, plain, (uint32_t)16U);
for (uint32_t i = (uint32_t)0U; i < (uint32_t)16U; i = i + (uint32_t)1U) {
uint32_t xi = ib[i];
uint32_t yi = k[i];
ob[i] = xi ^ yi;
}
Hacl_Lib_LoadStore32_uint32s_to_le_bytes(output, ob, (uint32_t)16U);
}
static void
Hacl_Impl_Chacha20_update_last(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint32_t *st,
uint32_t ctr)
{
uint8_t block[64U] = { 0U };
Hacl_Impl_Chacha20_chacha20_block(block, st, ctr);
uint8_t *mask = block;
for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
uint8_t xi = plain[i];
uint8_t yi = mask[i];
output[i] = xi ^ yi;
}
}
static void
Hacl_Impl_Chacha20_chacha20_counter_mode_blocks(
uint8_t *output,
uint8_t *plain,
uint32_t num_blocks,
uint32_t *st,
uint32_t ctr)
{
for (uint32_t i = (uint32_t)0U; i < num_blocks; i = i + (uint32_t)1U) {
uint8_t *b = plain + (uint32_t)64U * i;
uint8_t *o = output + (uint32_t)64U * i;
Hacl_Impl_Chacha20_update(o, b, st, ctr + i);
}
}
static void
Hacl_Impl_Chacha20_chacha20_counter_mode(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint32_t *st,
uint32_t ctr)
{
uint32_t blocks_len = len >> (uint32_t)6U;
uint32_t part_len = len & (uint32_t)0x3fU;
uint8_t *output_ = output;
uint8_t *plain_ = plain;
uint8_t *output__ = output + (uint32_t)64U * blocks_len;
uint8_t *plain__ = plain + (uint32_t)64U * blocks_len;
Hacl_Impl_Chacha20_chacha20_counter_mode_blocks(output_, plain_, blocks_len, st, ctr);
if (part_len > (uint32_t)0U)
Hacl_Impl_Chacha20_update_last(output__, plain__, part_len, st, ctr + blocks_len);
}
static void
Hacl_Impl_Chacha20_chacha20(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint8_t *k,
uint8_t *n1,
uint32_t ctr)
{
uint32_t buf[16U] = { 0U };
uint32_t *st = buf;
Hacl_Impl_Chacha20_init(st, k, n1);
Hacl_Impl_Chacha20_chacha20_counter_mode(output, plain, len, st, ctr);
}
void
Hacl_Chacha20_chacha20_key_block(uint8_t *block, uint8_t *k, uint8_t *n1, uint32_t ctr)
{
uint32_t buf[16U] = { 0U };
uint32_t *st = buf;
Hacl_Impl_Chacha20_init(st, k, n1);
Hacl_Impl_Chacha20_chacha20_block(block, st, ctr);
}
/*
This function implements Chacha20
val chacha20 :
output:uint8_p ->
plain:uint8_p{ disjoint output plain } ->
len:uint32_t{ v len = length output /\ v len = length plain } ->
key:uint8_p{ length key = 32 } ->
nonce:uint8_p{ length nonce = 12 } ->
ctr:uint32_t{ v ctr + length plain / 64 < pow2 32 } ->
Stack unit
(requires
fun h -> live h output /\ live h plain /\ live h nonce /\ live h key)
(ensures
fun h0 _ h1 ->
live h1 output /\ live h0 plain /\ modifies_1 output h0 h1 /\
live h0 nonce /\
live h0 key /\
h1.[ output ] ==
chacha20_encrypt_bytes h0.[ key ] h0.[ nonce ] (v ctr) h0.[ plain ])
*/
void
Hacl_Chacha20_chacha20(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint8_t *k,
uint8_t *n1,
uint32_t ctr)
{
Hacl_Impl_Chacha20_chacha20(output, plain, len, k, n1, ctr);
}

View file

@ -0,0 +1,81 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kremlib.h"
#ifndef __Hacl_Chacha20_H
#define __Hacl_Chacha20_H
typedef uint32_t Hacl_Impl_Xor_Lemmas_u32;
typedef uint8_t Hacl_Impl_Xor_Lemmas_u8;
typedef uint8_t *Hacl_Lib_LoadStore32_uint8_p;
typedef uint32_t Hacl_Impl_Chacha20_u32;
typedef uint32_t Hacl_Impl_Chacha20_h32;
typedef uint8_t *Hacl_Impl_Chacha20_uint8_p;
typedef uint32_t *Hacl_Impl_Chacha20_state;
typedef uint32_t Hacl_Impl_Chacha20_idx;
typedef struct
{
void *k;
void *n;
} Hacl_Impl_Chacha20_log_t_;
typedef void *Hacl_Impl_Chacha20_log_t;
typedef uint32_t Hacl_Lib_Create_h32;
typedef uint8_t *Hacl_Chacha20_uint8_p;
typedef uint32_t Hacl_Chacha20_uint32_t;
void Hacl_Chacha20_chacha20_key_block(uint8_t *block, uint8_t *k, uint8_t *n1, uint32_t ctr);
/*
This function implements Chacha20
val chacha20 :
output:uint8_p ->
plain:uint8_p{ disjoint output plain } ->
len:uint32_t{ v len = length output /\ v len = length plain } ->
key:uint8_p{ length key = 32 } ->
nonce:uint8_p{ length nonce = 12 } ->
ctr:uint32_t{ v ctr + length plain / 64 < pow2 32 } ->
Stack unit
(requires
fun h -> live h output /\ live h plain /\ live h nonce /\ live h key)
(ensures
fun h0 _ h1 ->
live h1 output /\ live h0 plain /\ modifies_1 output h0 h1 /\
live h0 nonce /\
live h0 key /\
h1.[ output ] ==
chacha20_encrypt_bytes h0.[ key ] h0.[ nonce ] (v ctr) h0.[ plain ])
*/
void
Hacl_Chacha20_chacha20(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint8_t *k,
uint8_t *n1,
uint32_t ctr);
#endif

View file

@ -0,0 +1,845 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Hacl_Curve25519.h"
static void
Hacl_Bignum_Modulo_carry_top(uint64_t *b)
{
uint64_t b4 = b[4U];
uint64_t b0 = b[0U];
uint64_t b4_ = b4 & (uint64_t)0x7ffffffffffffU;
uint64_t b0_ = b0 + (uint64_t)19U * (b4 >> (uint32_t)51U);
b[4U] = b4_;
b[0U] = b0_;
}
inline static void
Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, FStar_UInt128_t *input)
{
{
FStar_UInt128_t xi = input[0U];
output[0U] = FStar_UInt128_uint128_to_uint64(xi);
}
{
FStar_UInt128_t xi = input[1U];
output[1U] = FStar_UInt128_uint128_to_uint64(xi);
}
{
FStar_UInt128_t xi = input[2U];
output[2U] = FStar_UInt128_uint128_to_uint64(xi);
}
{
FStar_UInt128_t xi = input[3U];
output[3U] = FStar_UInt128_uint128_to_uint64(xi);
}
{
FStar_UInt128_t xi = input[4U];
output[4U] = FStar_UInt128_uint128_to_uint64(xi);
}
}
inline static void
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(
FStar_UInt128_t *output,
uint64_t *input,
uint64_t s)
{
{
FStar_UInt128_t xi = output[0U];
uint64_t yi = input[0U];
output[0U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
}
{
FStar_UInt128_t xi = output[1U];
uint64_t yi = input[1U];
output[1U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
}
{
FStar_UInt128_t xi = output[2U];
uint64_t yi = input[2U];
output[2U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
}
{
FStar_UInt128_t xi = output[3U];
uint64_t yi = input[3U];
output[3U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
}
{
FStar_UInt128_t xi = output[4U];
uint64_t yi = input[4U];
output[4U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
}
}
inline static void
Hacl_Bignum_Fproduct_carry_wide_(FStar_UInt128_t *tmp)
{
{
uint32_t ctr = (uint32_t)0U;
FStar_UInt128_t tctr = tmp[ctr];
FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U];
uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU;
FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U);
tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);
tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);
}
{
uint32_t ctr = (uint32_t)1U;
FStar_UInt128_t tctr = tmp[ctr];
FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U];
uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU;
FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U);
tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);
tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);
}
{
uint32_t ctr = (uint32_t)2U;
FStar_UInt128_t tctr = tmp[ctr];
FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U];
uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU;
FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U);
tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);
tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);
}
{
uint32_t ctr = (uint32_t)3U;
FStar_UInt128_t tctr = tmp[ctr];
FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U];
uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU;
FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U);
tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);
tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);
}
}
inline static void
Hacl_Bignum_Fmul_shift_reduce(uint64_t *output)
{
uint64_t tmp = output[4U];
{
uint32_t ctr = (uint32_t)5U - (uint32_t)0U - (uint32_t)1U;
uint64_t z = output[ctr - (uint32_t)1U];
output[ctr] = z;
}
{
uint32_t ctr = (uint32_t)5U - (uint32_t)1U - (uint32_t)1U;
uint64_t z = output[ctr - (uint32_t)1U];
output[ctr] = z;
}
{
uint32_t ctr = (uint32_t)5U - (uint32_t)2U - (uint32_t)1U;
uint64_t z = output[ctr - (uint32_t)1U];
output[ctr] = z;
}
{
uint32_t ctr = (uint32_t)5U - (uint32_t)3U - (uint32_t)1U;
uint64_t z = output[ctr - (uint32_t)1U];
output[ctr] = z;
}
output[0U] = tmp;
uint64_t b0 = output[0U];
output[0U] = (uint64_t)19U * b0;
}
static void
Hacl_Bignum_Fmul_mul_shift_reduce_(FStar_UInt128_t *output, uint64_t *input, uint64_t *input21)
{
{
uint64_t input2i = input21[0U];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
Hacl_Bignum_Fmul_shift_reduce(input);
}
{
uint64_t input2i = input21[1U];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
Hacl_Bignum_Fmul_shift_reduce(input);
}
{
uint64_t input2i = input21[2U];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
Hacl_Bignum_Fmul_shift_reduce(input);
}
{
uint64_t input2i = input21[3U];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
Hacl_Bignum_Fmul_shift_reduce(input);
}
uint32_t i = (uint32_t)4U;
uint64_t input2i = input21[i];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
}
inline static void
Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input21)
{
uint64_t tmp[5U] = { 0U };
memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]);
KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U);
FStar_UInt128_t t[5U];
for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i)
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);
Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input21);
Hacl_Bignum_Fproduct_carry_wide_(t);
FStar_UInt128_t b4 = t[4U];
FStar_UInt128_t b0 = t[0U];
FStar_UInt128_t
b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU));
FStar_UInt128_t
b0_ =
FStar_UInt128_add(b0,
FStar_UInt128_mul_wide((uint64_t)19U,
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U))));
t[4U] = b4_;
t[0U] = b0_;
Hacl_Bignum_Fproduct_copy_from_wide_(output, t);
uint64_t i0 = output[0U];
uint64_t i1 = output[1U];
uint64_t i0_ = i0 & (uint64_t)0x7ffffffffffffU;
uint64_t i1_ = i1 + (i0 >> (uint32_t)51U);
output[0U] = i0_;
output[1U] = i1_;
}
inline static void
Hacl_Bignum_Fsquare_fsquare__(FStar_UInt128_t *tmp, uint64_t *output)
{
uint64_t r0 = output[0U];
uint64_t r1 = output[1U];
uint64_t r2 = output[2U];
uint64_t r3 = output[3U];
uint64_t r4 = output[4U];
uint64_t d0 = r0 * (uint64_t)2U;
uint64_t d1 = r1 * (uint64_t)2U;
uint64_t d2 = r2 * (uint64_t)2U * (uint64_t)19U;
uint64_t d419 = r4 * (uint64_t)19U;
uint64_t d4 = d419 * (uint64_t)2U;
FStar_UInt128_t
s0 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(r0, r0),
FStar_UInt128_mul_wide(d4, r1)),
FStar_UInt128_mul_wide(d2, r3));
FStar_UInt128_t
s1 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r1),
FStar_UInt128_mul_wide(d4, r2)),
FStar_UInt128_mul_wide(r3 * (uint64_t)19U, r3));
FStar_UInt128_t
s2 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r2),
FStar_UInt128_mul_wide(r1, r1)),
FStar_UInt128_mul_wide(d4, r3));
FStar_UInt128_t
s3 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r3),
FStar_UInt128_mul_wide(d1, r2)),
FStar_UInt128_mul_wide(r4, d419));
FStar_UInt128_t
s4 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r4),
FStar_UInt128_mul_wide(d1, r3)),
FStar_UInt128_mul_wide(r2, r2));
tmp[0U] = s0;
tmp[1U] = s1;
tmp[2U] = s2;
tmp[3U] = s3;
tmp[4U] = s4;
}
inline static void
Hacl_Bignum_Fsquare_fsquare_(FStar_UInt128_t *tmp, uint64_t *output)
{
Hacl_Bignum_Fsquare_fsquare__(tmp, output);
Hacl_Bignum_Fproduct_carry_wide_(tmp);
FStar_UInt128_t b4 = tmp[4U];
FStar_UInt128_t b0 = tmp[0U];
FStar_UInt128_t
b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU));
FStar_UInt128_t
b0_ =
FStar_UInt128_add(b0,
FStar_UInt128_mul_wide((uint64_t)19U,
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U))));
tmp[4U] = b4_;
tmp[0U] = b0_;
Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp);
uint64_t i0 = output[0U];
uint64_t i1 = output[1U];
uint64_t i0_ = i0 & (uint64_t)0x7ffffffffffffU;
uint64_t i1_ = i1 + (i0 >> (uint32_t)51U);
output[0U] = i0_;
output[1U] = i1_;
}
static void
Hacl_Bignum_Fsquare_fsquare_times_(uint64_t *input, FStar_UInt128_t *tmp, uint32_t count1)
{
Hacl_Bignum_Fsquare_fsquare_(tmp, input);
for (uint32_t i = (uint32_t)1U; i < count1; i = i + (uint32_t)1U)
Hacl_Bignum_Fsquare_fsquare_(tmp, input);
}
inline static void
Hacl_Bignum_Fsquare_fsquare_times(uint64_t *output, uint64_t *input, uint32_t count1)
{
KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U);
FStar_UInt128_t t[5U];
for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i)
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);
memcpy(output, input, (uint32_t)5U * sizeof input[0U]);
Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1);
}
inline static void
Hacl_Bignum_Fsquare_fsquare_times_inplace(uint64_t *output, uint32_t count1)
{
KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U);
FStar_UInt128_t t[5U];
for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i)
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);
Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1);
}
inline static void
Hacl_Bignum_Crecip_crecip(uint64_t *out, uint64_t *z)
{
uint64_t buf[20U] = { 0U };
uint64_t *a = buf;
uint64_t *t00 = buf + (uint32_t)5U;
uint64_t *b0 = buf + (uint32_t)10U;
Hacl_Bignum_Fsquare_fsquare_times(a, z, (uint32_t)1U);
Hacl_Bignum_Fsquare_fsquare_times(t00, a, (uint32_t)2U);
Hacl_Bignum_Fmul_fmul(b0, t00, z);
Hacl_Bignum_Fmul_fmul(a, b0, a);
Hacl_Bignum_Fsquare_fsquare_times(t00, a, (uint32_t)1U);
Hacl_Bignum_Fmul_fmul(b0, t00, b0);
Hacl_Bignum_Fsquare_fsquare_times(t00, b0, (uint32_t)5U);
uint64_t *t01 = buf + (uint32_t)5U;
uint64_t *b1 = buf + (uint32_t)10U;
uint64_t *c0 = buf + (uint32_t)15U;
Hacl_Bignum_Fmul_fmul(b1, t01, b1);
Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)10U);
Hacl_Bignum_Fmul_fmul(c0, t01, b1);
Hacl_Bignum_Fsquare_fsquare_times(t01, c0, (uint32_t)20U);
Hacl_Bignum_Fmul_fmul(t01, t01, c0);
Hacl_Bignum_Fsquare_fsquare_times_inplace(t01, (uint32_t)10U);
Hacl_Bignum_Fmul_fmul(b1, t01, b1);
Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)50U);
uint64_t *a0 = buf;
uint64_t *t0 = buf + (uint32_t)5U;
uint64_t *b = buf + (uint32_t)10U;
uint64_t *c = buf + (uint32_t)15U;
Hacl_Bignum_Fmul_fmul(c, t0, b);
Hacl_Bignum_Fsquare_fsquare_times(t0, c, (uint32_t)100U);
Hacl_Bignum_Fmul_fmul(t0, t0, c);
Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)50U);
Hacl_Bignum_Fmul_fmul(t0, t0, b);
Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)5U);
Hacl_Bignum_Fmul_fmul(out, t0, a0);
}
inline static void
Hacl_Bignum_fsum(uint64_t *a, uint64_t *b)
{
{
uint64_t xi = a[0U];
uint64_t yi = b[0U];
a[0U] = xi + yi;
}
{
uint64_t xi = a[1U];
uint64_t yi = b[1U];
a[1U] = xi + yi;
}
{
uint64_t xi = a[2U];
uint64_t yi = b[2U];
a[2U] = xi + yi;
}
{
uint64_t xi = a[3U];
uint64_t yi = b[3U];
a[3U] = xi + yi;
}
{
uint64_t xi = a[4U];
uint64_t yi = b[4U];
a[4U] = xi + yi;
}
}
inline static void
Hacl_Bignum_fdifference(uint64_t *a, uint64_t *b)
{
uint64_t tmp[5U] = { 0U };
memcpy(tmp, b, (uint32_t)5U * sizeof b[0U]);
uint64_t b0 = tmp[0U];
uint64_t b1 = tmp[1U];
uint64_t b2 = tmp[2U];
uint64_t b3 = tmp[3U];
uint64_t b4 = tmp[4U];
tmp[0U] = b0 + (uint64_t)0x3fffffffffff68U;
tmp[1U] = b1 + (uint64_t)0x3ffffffffffff8U;
tmp[2U] = b2 + (uint64_t)0x3ffffffffffff8U;
tmp[3U] = b3 + (uint64_t)0x3ffffffffffff8U;
tmp[4U] = b4 + (uint64_t)0x3ffffffffffff8U;
{
uint64_t xi = a[0U];
uint64_t yi = tmp[0U];
a[0U] = yi - xi;
}
{
uint64_t xi = a[1U];
uint64_t yi = tmp[1U];
a[1U] = yi - xi;
}
{
uint64_t xi = a[2U];
uint64_t yi = tmp[2U];
a[2U] = yi - xi;
}
{
uint64_t xi = a[3U];
uint64_t yi = tmp[3U];
a[3U] = yi - xi;
}
{
uint64_t xi = a[4U];
uint64_t yi = tmp[4U];
a[4U] = yi - xi;
}
}
inline static void
Hacl_Bignum_fscalar(uint64_t *output, uint64_t *b, uint64_t s)
{
KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U);
FStar_UInt128_t tmp[5U];
for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i)
tmp[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);
{
uint64_t xi = b[0U];
tmp[0U] = FStar_UInt128_mul_wide(xi, s);
}
{
uint64_t xi = b[1U];
tmp[1U] = FStar_UInt128_mul_wide(xi, s);
}
{
uint64_t xi = b[2U];
tmp[2U] = FStar_UInt128_mul_wide(xi, s);
}
{
uint64_t xi = b[3U];
tmp[3U] = FStar_UInt128_mul_wide(xi, s);
}
{
uint64_t xi = b[4U];
tmp[4U] = FStar_UInt128_mul_wide(xi, s);
}
Hacl_Bignum_Fproduct_carry_wide_(tmp);
FStar_UInt128_t b4 = tmp[4U];
FStar_UInt128_t b0 = tmp[0U];
FStar_UInt128_t
b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU));
FStar_UInt128_t
b0_ =
FStar_UInt128_add(b0,
FStar_UInt128_mul_wide((uint64_t)19U,
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U))));
tmp[4U] = b4_;
tmp[0U] = b0_;
Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp);
}
inline static void
Hacl_Bignum_fmul(uint64_t *output, uint64_t *a, uint64_t *b)
{
Hacl_Bignum_Fmul_fmul(output, a, b);
}
inline static void
Hacl_Bignum_crecip(uint64_t *output, uint64_t *input)
{
Hacl_Bignum_Crecip_crecip(output, input);
}
static void
Hacl_EC_Point_swap_conditional_step(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr)
{
uint32_t i = ctr - (uint32_t)1U;
uint64_t ai = a[i];
uint64_t bi = b[i];
uint64_t x = swap1 & (ai ^ bi);
uint64_t ai1 = ai ^ x;
uint64_t bi1 = bi ^ x;
a[i] = ai1;
b[i] = bi1;
}
static void
Hacl_EC_Point_swap_conditional_(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr)
{
if (!(ctr == (uint32_t)0U)) {
Hacl_EC_Point_swap_conditional_step(a, b, swap1, ctr);
uint32_t i = ctr - (uint32_t)1U;
Hacl_EC_Point_swap_conditional_(a, b, swap1, i);
}
}
static void
Hacl_EC_Point_swap_conditional(uint64_t *a, uint64_t *b, uint64_t iswap)
{
uint64_t swap1 = (uint64_t)0U - iswap;
Hacl_EC_Point_swap_conditional_(a, b, swap1, (uint32_t)5U);
Hacl_EC_Point_swap_conditional_(a + (uint32_t)5U, b + (uint32_t)5U, swap1, (uint32_t)5U);
}
static void
Hacl_EC_Point_copy(uint64_t *output, uint64_t *input)
{
memcpy(output, input, (uint32_t)5U * sizeof input[0U]);
memcpy(output + (uint32_t)5U,
input + (uint32_t)5U,
(uint32_t)5U * sizeof(input + (uint32_t)5U)[0U]);
}
static void
Hacl_EC_AddAndDouble_fmonty(
uint64_t *pp,
uint64_t *ppq,
uint64_t *p,
uint64_t *pq,
uint64_t *qmqp)
{
uint64_t *qx = qmqp;
uint64_t *x2 = pp;
uint64_t *z2 = pp + (uint32_t)5U;
uint64_t *x3 = ppq;
uint64_t *z3 = ppq + (uint32_t)5U;
uint64_t *x = p;
uint64_t *z = p + (uint32_t)5U;
uint64_t *xprime = pq;
uint64_t *zprime = pq + (uint32_t)5U;
uint64_t buf[40U] = { 0U };
uint64_t *origx = buf;
uint64_t *origxprime = buf + (uint32_t)5U;
uint64_t *xxprime0 = buf + (uint32_t)25U;
uint64_t *zzprime0 = buf + (uint32_t)30U;
memcpy(origx, x, (uint32_t)5U * sizeof x[0U]);
Hacl_Bignum_fsum(x, z);
Hacl_Bignum_fdifference(z, origx);
memcpy(origxprime, xprime, (uint32_t)5U * sizeof xprime[0U]);
Hacl_Bignum_fsum(xprime, zprime);
Hacl_Bignum_fdifference(zprime, origxprime);
Hacl_Bignum_fmul(xxprime0, xprime, z);
Hacl_Bignum_fmul(zzprime0, x, zprime);
uint64_t *origxprime0 = buf + (uint32_t)5U;
uint64_t *xx0 = buf + (uint32_t)15U;
uint64_t *zz0 = buf + (uint32_t)20U;
uint64_t *xxprime = buf + (uint32_t)25U;
uint64_t *zzprime = buf + (uint32_t)30U;
uint64_t *zzzprime = buf + (uint32_t)35U;
memcpy(origxprime0, xxprime, (uint32_t)5U * sizeof xxprime[0U]);
Hacl_Bignum_fsum(xxprime, zzprime);
Hacl_Bignum_fdifference(zzprime, origxprime0);
Hacl_Bignum_Fsquare_fsquare_times(x3, xxprime, (uint32_t)1U);
Hacl_Bignum_Fsquare_fsquare_times(zzzprime, zzprime, (uint32_t)1U);
Hacl_Bignum_fmul(z3, zzzprime, qx);
Hacl_Bignum_Fsquare_fsquare_times(xx0, x, (uint32_t)1U);
Hacl_Bignum_Fsquare_fsquare_times(zz0, z, (uint32_t)1U);
uint64_t *zzz = buf + (uint32_t)10U;
uint64_t *xx = buf + (uint32_t)15U;
uint64_t *zz = buf + (uint32_t)20U;
Hacl_Bignum_fmul(x2, xx, zz);
Hacl_Bignum_fdifference(zz, xx);
uint64_t scalar = (uint64_t)121665U;
Hacl_Bignum_fscalar(zzz, zz, scalar);
Hacl_Bignum_fsum(zzz, xx);
Hacl_Bignum_fmul(z2, zzz, zz);
}
static void
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(
uint64_t *nq,
uint64_t *nqpq,
uint64_t *nq2,
uint64_t *nqpq2,
uint64_t *q,
uint8_t byt)
{
uint64_t bit = (uint64_t)(byt >> (uint32_t)7U);
Hacl_EC_Point_swap_conditional(nq, nqpq, bit);
Hacl_EC_AddAndDouble_fmonty(nq2, nqpq2, nq, nqpq, q);
uint64_t bit0 = (uint64_t)(byt >> (uint32_t)7U);
Hacl_EC_Point_swap_conditional(nq2, nqpq2, bit0);
}
static void
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(
uint64_t *nq,
uint64_t *nqpq,
uint64_t *nq2,
uint64_t *nqpq2,
uint64_t *q,
uint8_t byt)
{
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq, nqpq, nq2, nqpq2, q, byt);
uint8_t byt1 = byt << (uint32_t)1U;
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq2, nqpq2, nq, nqpq, q, byt1);
}
static void
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(
uint64_t *nq,
uint64_t *nqpq,
uint64_t *nq2,
uint64_t *nqpq2,
uint64_t *q,
uint8_t byt,
uint32_t i)
{
if (!(i == (uint32_t)0U)) {
uint32_t i_ = i - (uint32_t)1U;
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(nq, nqpq, nq2, nqpq2, q, byt);
uint8_t byt_ = byt << (uint32_t)2U;
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byt_, i_);
}
}
static void
Hacl_EC_Ladder_BigLoop_cmult_big_loop(
uint8_t *n1,
uint64_t *nq,
uint64_t *nqpq,
uint64_t *nq2,
uint64_t *nqpq2,
uint64_t *q,
uint32_t i)
{
if (!(i == (uint32_t)0U)) {
uint32_t i1 = i - (uint32_t)1U;
uint8_t byte = n1[i1];
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byte, (uint32_t)4U);
Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, i1);
}
}
static void
Hacl_EC_Ladder_cmult(uint64_t *result, uint8_t *n1, uint64_t *q)
{
uint64_t point_buf[40U] = { 0U };
uint64_t *nq = point_buf;
uint64_t *nqpq = point_buf + (uint32_t)10U;
uint64_t *nq2 = point_buf + (uint32_t)20U;
uint64_t *nqpq2 = point_buf + (uint32_t)30U;
Hacl_EC_Point_copy(nqpq, q);
nq[0U] = (uint64_t)1U;
Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, (uint32_t)32U);
Hacl_EC_Point_copy(result, nq);
}
static void
Hacl_EC_Format_fexpand(uint64_t *output, uint8_t *input)
{
uint64_t i0 = load64_le(input);
uint8_t *x00 = input + (uint32_t)6U;
uint64_t i1 = load64_le(x00);
uint8_t *x01 = input + (uint32_t)12U;
uint64_t i2 = load64_le(x01);
uint8_t *x02 = input + (uint32_t)19U;
uint64_t i3 = load64_le(x02);
uint8_t *x0 = input + (uint32_t)24U;
uint64_t i4 = load64_le(x0);
uint64_t output0 = i0 & (uint64_t)0x7ffffffffffffU;
uint64_t output1 = i1 >> (uint32_t)3U & (uint64_t)0x7ffffffffffffU;
uint64_t output2 = i2 >> (uint32_t)6U & (uint64_t)0x7ffffffffffffU;
uint64_t output3 = i3 >> (uint32_t)1U & (uint64_t)0x7ffffffffffffU;
uint64_t output4 = i4 >> (uint32_t)12U & (uint64_t)0x7ffffffffffffU;
output[0U] = output0;
output[1U] = output1;
output[2U] = output2;
output[3U] = output3;
output[4U] = output4;
}
static void
Hacl_EC_Format_fcontract_first_carry_pass(uint64_t *input)
{
uint64_t t0 = input[0U];
uint64_t t1 = input[1U];
uint64_t t2 = input[2U];
uint64_t t3 = input[3U];
uint64_t t4 = input[4U];
uint64_t t1_ = t1 + (t0 >> (uint32_t)51U);
uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU;
uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U);
uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU;
uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U);
uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU;
uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U);
uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU;
input[0U] = t0_;
input[1U] = t1__;
input[2U] = t2__;
input[3U] = t3__;
input[4U] = t4_;
}
static void
Hacl_EC_Format_fcontract_first_carry_full(uint64_t *input)
{
Hacl_EC_Format_fcontract_first_carry_pass(input);
Hacl_Bignum_Modulo_carry_top(input);
}
static void
Hacl_EC_Format_fcontract_second_carry_pass(uint64_t *input)
{
uint64_t t0 = input[0U];
uint64_t t1 = input[1U];
uint64_t t2 = input[2U];
uint64_t t3 = input[3U];
uint64_t t4 = input[4U];
uint64_t t1_ = t1 + (t0 >> (uint32_t)51U);
uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU;
uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U);
uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU;
uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U);
uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU;
uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U);
uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU;
input[0U] = t0_;
input[1U] = t1__;
input[2U] = t2__;
input[3U] = t3__;
input[4U] = t4_;
}
static void
Hacl_EC_Format_fcontract_second_carry_full(uint64_t *input)
{
Hacl_EC_Format_fcontract_second_carry_pass(input);
Hacl_Bignum_Modulo_carry_top(input);
uint64_t i0 = input[0U];
uint64_t i1 = input[1U];
uint64_t i0_ = i0 & (uint64_t)0x7ffffffffffffU;
uint64_t i1_ = i1 + (i0 >> (uint32_t)51U);
input[0U] = i0_;
input[1U] = i1_;
}
static void
Hacl_EC_Format_fcontract_trim(uint64_t *input)
{
uint64_t a0 = input[0U];
uint64_t a1 = input[1U];
uint64_t a2 = input[2U];
uint64_t a3 = input[3U];
uint64_t a4 = input[4U];
uint64_t mask0 = FStar_UInt64_gte_mask(a0, (uint64_t)0x7ffffffffffedU);
uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0x7ffffffffffffU);
uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x7ffffffffffffU);
uint64_t mask3 = FStar_UInt64_eq_mask(a3, (uint64_t)0x7ffffffffffffU);
uint64_t mask4 = FStar_UInt64_eq_mask(a4, (uint64_t)0x7ffffffffffffU);
uint64_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4;
uint64_t a0_ = a0 - ((uint64_t)0x7ffffffffffedU & mask);
uint64_t a1_ = a1 - ((uint64_t)0x7ffffffffffffU & mask);
uint64_t a2_ = a2 - ((uint64_t)0x7ffffffffffffU & mask);
uint64_t a3_ = a3 - ((uint64_t)0x7ffffffffffffU & mask);
uint64_t a4_ = a4 - ((uint64_t)0x7ffffffffffffU & mask);
input[0U] = a0_;
input[1U] = a1_;
input[2U] = a2_;
input[3U] = a3_;
input[4U] = a4_;
}
static void
Hacl_EC_Format_fcontract_store(uint8_t *output, uint64_t *input)
{
uint64_t t0 = input[0U];
uint64_t t1 = input[1U];
uint64_t t2 = input[2U];
uint64_t t3 = input[3U];
uint64_t t4 = input[4U];
uint64_t o0 = t1 << (uint32_t)51U | t0;
uint64_t o1 = t2 << (uint32_t)38U | t1 >> (uint32_t)13U;
uint64_t o2 = t3 << (uint32_t)25U | t2 >> (uint32_t)26U;
uint64_t o3 = t4 << (uint32_t)12U | t3 >> (uint32_t)39U;
uint8_t *b0 = output;
uint8_t *b1 = output + (uint32_t)8U;
uint8_t *b2 = output + (uint32_t)16U;
uint8_t *b3 = output + (uint32_t)24U;
store64_le(b0, o0);
store64_le(b1, o1);
store64_le(b2, o2);
store64_le(b3, o3);
}
static void
Hacl_EC_Format_fcontract(uint8_t *output, uint64_t *input)
{
Hacl_EC_Format_fcontract_first_carry_full(input);
Hacl_EC_Format_fcontract_second_carry_full(input);
Hacl_EC_Format_fcontract_trim(input);
Hacl_EC_Format_fcontract_store(output, input);
}
static void
Hacl_EC_Format_scalar_of_point(uint8_t *scalar, uint64_t *point)
{
uint64_t *x = point;
uint64_t *z = point + (uint32_t)5U;
uint64_t buf[10U] = { 0U };
uint64_t *zmone = buf;
uint64_t *sc = buf + (uint32_t)5U;
Hacl_Bignum_crecip(zmone, z);
Hacl_Bignum_fmul(sc, x, zmone);
Hacl_EC_Format_fcontract(scalar, sc);
}
void
Hacl_EC_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint)
{
uint64_t buf0[10U] = { 0U };
uint64_t *x0 = buf0;
uint64_t *z = buf0 + (uint32_t)5U;
Hacl_EC_Format_fexpand(x0, basepoint);
z[0U] = (uint64_t)1U;
uint64_t *q = buf0;
uint8_t e[32U] = { 0U };
memcpy(e, secret, (uint32_t)32U * sizeof secret[0U]);
uint8_t e0 = e[0U];
uint8_t e31 = e[31U];
uint8_t e01 = e0 & (uint8_t)248U;
uint8_t e311 = e31 & (uint8_t)127U;
uint8_t e312 = e311 | (uint8_t)64U;
e[0U] = e01;
e[31U] = e312;
uint8_t *scalar = e;
uint64_t buf[15U] = { 0U };
uint64_t *nq = buf;
uint64_t *x = nq;
x[0U] = (uint64_t)1U;
Hacl_EC_Ladder_cmult(nq, scalar, q);
Hacl_EC_Format_scalar_of_point(mypublic, nq);
}
void
Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint)
{
Hacl_EC_crypto_scalarmult(mypublic, secret, basepoint);
}

View file

@ -0,0 +1,57 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kremlib.h"
#ifndef __Hacl_Curve25519_H
#define __Hacl_Curve25519_H
typedef uint64_t Hacl_Bignum_Constants_limb;
typedef FStar_UInt128_t Hacl_Bignum_Constants_wide;
typedef uint64_t Hacl_Bignum_Parameters_limb;
typedef FStar_UInt128_t Hacl_Bignum_Parameters_wide;
typedef uint32_t Hacl_Bignum_Parameters_ctr;
typedef uint64_t *Hacl_Bignum_Parameters_felem;
typedef FStar_UInt128_t *Hacl_Bignum_Parameters_felem_wide;
typedef void *Hacl_Bignum_Parameters_seqelem;
typedef void *Hacl_Bignum_Parameters_seqelem_wide;
typedef FStar_UInt128_t Hacl_Bignum_Wide_t;
typedef uint64_t Hacl_Bignum_Limb_t;
extern void Hacl_Bignum_lemma_diff(Prims_int x0, Prims_int x1, Prims_pos x2);
typedef uint64_t *Hacl_EC_Point_point;
typedef uint8_t *Hacl_EC_Ladder_SmallLoop_uint8_p;
typedef uint8_t *Hacl_EC_Ladder_uint8_p;
typedef uint8_t *Hacl_EC_Format_uint8_p;
void Hacl_EC_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint);
typedef uint8_t *Hacl_Curve25519_uint8_p;
void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint);
#endif

View file

@ -0,0 +1,485 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Hacl_Poly1305_64.h"
inline static void
Hacl_Bignum_Modulo_reduce(uint64_t *b)
{
uint64_t b0 = b[0U];
b[0U] = (b0 << (uint32_t)4U) + (b0 << (uint32_t)2U);
}
inline static void
Hacl_Bignum_Modulo_carry_top(uint64_t *b)
{
uint64_t b2 = b[2U];
uint64_t b0 = b[0U];
uint64_t b2_42 = b2 >> (uint32_t)42U;
b[2U] = b2 & (uint64_t)0x3ffffffffffU;
b[0U] = (b2_42 << (uint32_t)2U) + b2_42 + b0;
}
inline static void
Hacl_Bignum_Modulo_carry_top_wide(FStar_UInt128_t *b)
{
FStar_UInt128_t b2 = b[2U];
FStar_UInt128_t b0 = b[0U];
FStar_UInt128_t
b2_ = FStar_UInt128_logand(b2, FStar_UInt128_uint64_to_uint128((uint64_t)0x3ffffffffffU));
uint64_t b2_42 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b2, (uint32_t)42U));
FStar_UInt128_t
b0_ = FStar_UInt128_add(b0, FStar_UInt128_uint64_to_uint128((b2_42 << (uint32_t)2U) + b2_42));
b[2U] = b2_;
b[0U] = b0_;
}
inline static void
Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, FStar_UInt128_t *input)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)3U; i = i + (uint32_t)1U) {
FStar_UInt128_t xi = input[i];
output[i] = FStar_UInt128_uint128_to_uint64(xi);
}
}
inline static void
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(
FStar_UInt128_t *output,
uint64_t *input,
uint64_t s)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)3U; i = i + (uint32_t)1U) {
FStar_UInt128_t xi = output[i];
uint64_t yi = input[i];
output[i] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
}
}
inline static void
Hacl_Bignum_Fproduct_carry_wide_(FStar_UInt128_t *tmp)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
uint32_t ctr = i;
FStar_UInt128_t tctr = tmp[ctr];
FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U];
uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0xfffffffffffU;
FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)44U);
tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);
tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);
}
}
inline static void
Hacl_Bignum_Fproduct_carry_limb_(uint64_t *tmp)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
uint32_t ctr = i;
uint64_t tctr = tmp[ctr];
uint64_t tctrp1 = tmp[ctr + (uint32_t)1U];
uint64_t r0 = tctr & (uint64_t)0xfffffffffffU;
uint64_t c = tctr >> (uint32_t)44U;
tmp[ctr] = r0;
tmp[ctr + (uint32_t)1U] = tctrp1 + c;
}
}
inline static void
Hacl_Bignum_Fmul_shift_reduce(uint64_t *output)
{
uint64_t tmp = output[2U];
for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
uint32_t ctr = (uint32_t)3U - i - (uint32_t)1U;
uint64_t z = output[ctr - (uint32_t)1U];
output[ctr] = z;
}
output[0U] = tmp;
Hacl_Bignum_Modulo_reduce(output);
}
static void
Hacl_Bignum_Fmul_mul_shift_reduce_(FStar_UInt128_t *output, uint64_t *input, uint64_t *input2)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
uint64_t input2i = input2[i];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
Hacl_Bignum_Fmul_shift_reduce(input);
}
uint32_t i = (uint32_t)2U;
uint64_t input2i = input2[i];
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
}
inline static void
Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input2)
{
uint64_t tmp[3U] = { 0U };
memcpy(tmp, input, (uint32_t)3U * sizeof input[0U]);
KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)3U);
FStar_UInt128_t t[3U];
for (uint32_t _i = 0U; _i < (uint32_t)3U; ++_i)
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);
Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2);
Hacl_Bignum_Fproduct_carry_wide_(t);
Hacl_Bignum_Modulo_carry_top_wide(t);
Hacl_Bignum_Fproduct_copy_from_wide_(output, t);
uint64_t i0 = output[0U];
uint64_t i1 = output[1U];
uint64_t i0_ = i0 & (uint64_t)0xfffffffffffU;
uint64_t i1_ = i1 + (i0 >> (uint32_t)44U);
output[0U] = i0_;
output[1U] = i1_;
}
inline static void
Hacl_Bignum_AddAndMultiply_add_and_multiply(uint64_t *acc, uint64_t *block, uint64_t *r)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)3U; i = i + (uint32_t)1U) {
uint64_t xi = acc[i];
uint64_t yi = block[i];
acc[i] = xi + yi;
}
Hacl_Bignum_Fmul_fmul(acc, acc, r);
}
inline static void
Hacl_Impl_Poly1305_64_poly1305_update(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m)
{
Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
uint64_t *h = scrut0.h;
uint64_t *acc = h;
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *r = scrut.r;
uint64_t *r3 = r;
uint64_t tmp[3U] = { 0U };
FStar_UInt128_t m0 = load128_le(m);
uint64_t r0 = FStar_UInt128_uint128_to_uint64(m0) & (uint64_t)0xfffffffffffU;
uint64_t
r1 =
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
uint64_t r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)88U));
tmp[0U] = r0;
tmp[1U] = r1;
tmp[2U] = r2;
uint64_t b2 = tmp[2U];
uint64_t b2_ = (uint64_t)0x10000000000U | b2;
tmp[2U] = b2_;
Hacl_Bignum_AddAndMultiply_add_and_multiply(acc, tmp, r3);
}
inline static void
Hacl_Impl_Poly1305_64_poly1305_process_last_block_(
uint8_t *block,
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint64_t rem_)
{
uint64_t tmp[3U] = { 0U };
FStar_UInt128_t m0 = load128_le(block);
uint64_t r0 = FStar_UInt128_uint128_to_uint64(m0) & (uint64_t)0xfffffffffffU;
uint64_t
r1 =
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
uint64_t r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)88U));
tmp[0U] = r0;
tmp[1U] = r1;
tmp[2U] = r2;
Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
uint64_t *h = scrut0.h;
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *r = scrut.r;
Hacl_Bignum_AddAndMultiply_add_and_multiply(h, tmp, r);
}
inline static void
Hacl_Impl_Poly1305_64_poly1305_process_last_block(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint64_t rem_)
{
uint8_t zero1 = (uint8_t)0U;
KRML_CHECK_SIZE(zero1, (uint32_t)16U);
uint8_t block[16U];
for (uint32_t _i = 0U; _i < (uint32_t)16U; ++_i)
block[_i] = zero1;
uint32_t i0 = (uint32_t)rem_;
uint32_t i = (uint32_t)rem_;
memcpy(block, m, i * sizeof m[0U]);
block[i0] = (uint8_t)1U;
Hacl_Impl_Poly1305_64_poly1305_process_last_block_(block, st, m, rem_);
}
static void
Hacl_Impl_Poly1305_64_poly1305_last_pass(uint64_t *acc)
{
Hacl_Bignum_Fproduct_carry_limb_(acc);
Hacl_Bignum_Modulo_carry_top(acc);
uint64_t a0 = acc[0U];
uint64_t a10 = acc[1U];
uint64_t a20 = acc[2U];
uint64_t a0_ = a0 & (uint64_t)0xfffffffffffU;
uint64_t r0 = a0 >> (uint32_t)44U;
uint64_t a1_ = (a10 + r0) & (uint64_t)0xfffffffffffU;
uint64_t r1 = (a10 + r0) >> (uint32_t)44U;
uint64_t a2_ = a20 + r1;
acc[0U] = a0_;
acc[1U] = a1_;
acc[2U] = a2_;
Hacl_Bignum_Modulo_carry_top(acc);
uint64_t i0 = acc[0U];
uint64_t i1 = acc[1U];
uint64_t i0_ = i0 & (uint64_t)0xfffffffffffU;
uint64_t i1_ = i1 + (i0 >> (uint32_t)44U);
acc[0U] = i0_;
acc[1U] = i1_;
uint64_t a00 = acc[0U];
uint64_t a1 = acc[1U];
uint64_t a2 = acc[2U];
uint64_t mask0 = FStar_UInt64_gte_mask(a00, (uint64_t)0xffffffffffbU);
uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0xfffffffffffU);
uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x3ffffffffffU);
uint64_t mask = (mask0 & mask1) & mask2;
uint64_t a0_0 = a00 - ((uint64_t)0xffffffffffbU & mask);
uint64_t a1_0 = a1 - ((uint64_t)0xfffffffffffU & mask);
uint64_t a2_0 = a2 - ((uint64_t)0x3ffffffffffU & mask);
acc[0U] = a0_0;
acc[1U] = a1_0;
acc[2U] = a2_0;
}
static Hacl_Impl_Poly1305_64_State_poly1305_state
Hacl_Impl_Poly1305_64_mk_state(uint64_t *r, uint64_t *h)
{
return ((Hacl_Impl_Poly1305_64_State_poly1305_state){.r = r, .h = h });
}
static void
Hacl_Standalone_Poly1305_64_poly1305_blocks(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint64_t len1)
{
if (!(len1 == (uint64_t)0U)) {
uint8_t *block = m;
uint8_t *tail1 = m + (uint32_t)16U;
Hacl_Impl_Poly1305_64_poly1305_update(st, block);
uint64_t len2 = len1 - (uint64_t)1U;
Hacl_Standalone_Poly1305_64_poly1305_blocks(st, tail1, len2);
}
}
static void
Hacl_Standalone_Poly1305_64_poly1305_partial(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *input,
uint64_t len1,
uint8_t *kr)
{
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *r = scrut.r;
uint64_t *x0 = r;
FStar_UInt128_t k1 = load128_le(kr);
FStar_UInt128_t
k_clamped =
FStar_UInt128_logand(k1,
FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0ffffffcU),
(uint32_t)64U),
FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0fffffffU)));
uint64_t r0 = FStar_UInt128_uint128_to_uint64(k_clamped) & (uint64_t)0xfffffffffffU;
uint64_t
r1 =
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
uint64_t
r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)88U));
x0[0U] = r0;
x0[1U] = r1;
x0[2U] = r2;
Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
uint64_t *h = scrut0.h;
uint64_t *x00 = h;
x00[0U] = (uint64_t)0U;
x00[1U] = (uint64_t)0U;
x00[2U] = (uint64_t)0U;
Hacl_Standalone_Poly1305_64_poly1305_blocks(st, input, len1);
}
static void
Hacl_Standalone_Poly1305_64_poly1305_complete(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint64_t len1,
uint8_t *k1)
{
uint8_t *kr = k1;
uint64_t len16 = len1 >> (uint32_t)4U;
uint64_t rem16 = len1 & (uint64_t)0xfU;
uint8_t *part_input = m;
uint8_t *last_block = m + (uint32_t)((uint64_t)16U * len16);
Hacl_Standalone_Poly1305_64_poly1305_partial(st, part_input, len16, kr);
if (!(rem16 == (uint64_t)0U))
Hacl_Impl_Poly1305_64_poly1305_process_last_block(st, last_block, rem16);
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *h = scrut.h;
uint64_t *acc = h;
Hacl_Impl_Poly1305_64_poly1305_last_pass(acc);
}
static void
Hacl_Standalone_Poly1305_64_crypto_onetimeauth_(
uint8_t *output,
uint8_t *input,
uint64_t len1,
uint8_t *k1)
{
uint64_t buf[6U] = { 0U };
uint64_t *r = buf;
uint64_t *h = buf + (uint32_t)3U;
Hacl_Impl_Poly1305_64_State_poly1305_state st = Hacl_Impl_Poly1305_64_mk_state(r, h);
uint8_t *key_s = k1 + (uint32_t)16U;
Hacl_Standalone_Poly1305_64_poly1305_complete(st, input, len1, k1);
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *h3 = scrut.h;
uint64_t *acc = h3;
FStar_UInt128_t k_ = load128_le(key_s);
uint64_t h0 = acc[0U];
uint64_t h1 = acc[1U];
uint64_t h2 = acc[2U];
FStar_UInt128_t
acc_ =
FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128(h2
<< (uint32_t)24U |
h1 >> (uint32_t)20U),
(uint32_t)64U),
FStar_UInt128_uint64_to_uint128(h1 << (uint32_t)44U | h0));
FStar_UInt128_t mac_ = FStar_UInt128_add_mod(acc_, k_);
store128_le(output, mac_);
}
static void
Hacl_Standalone_Poly1305_64_crypto_onetimeauth(
uint8_t *output,
uint8_t *input,
uint64_t len1,
uint8_t *k1)
{
Hacl_Standalone_Poly1305_64_crypto_onetimeauth_(output, input, len1, k1);
}
Hacl_Impl_Poly1305_64_State_poly1305_state
Hacl_Poly1305_64_mk_state(uint64_t *r, uint64_t *acc)
{
return Hacl_Impl_Poly1305_64_mk_state(r, acc);
}
void
Hacl_Poly1305_64_init(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *k1)
{
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *r = scrut.r;
uint64_t *x0 = r;
FStar_UInt128_t k10 = load128_le(k1);
FStar_UInt128_t
k_clamped =
FStar_UInt128_logand(k10,
FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0ffffffcU),
(uint32_t)64U),
FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0fffffffU)));
uint64_t r0 = FStar_UInt128_uint128_to_uint64(k_clamped) & (uint64_t)0xfffffffffffU;
uint64_t
r1 =
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
uint64_t
r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)88U));
x0[0U] = r0;
x0[1U] = r1;
x0[2U] = r2;
Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
uint64_t *h = scrut0.h;
uint64_t *x00 = h;
x00[0U] = (uint64_t)0U;
x00[1U] = (uint64_t)0U;
x00[2U] = (uint64_t)0U;
}
void
Hacl_Poly1305_64_update_block(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *m)
{
Hacl_Impl_Poly1305_64_poly1305_update(st, m);
}
void
Hacl_Poly1305_64_update(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint32_t num_blocks)
{
if (!(num_blocks == (uint32_t)0U)) {
uint8_t *block = m;
uint8_t *m_ = m + (uint32_t)16U;
uint32_t n1 = num_blocks - (uint32_t)1U;
Hacl_Poly1305_64_update_block(st, block);
Hacl_Poly1305_64_update(st, m_, n1);
}
}
void
Hacl_Poly1305_64_update_last(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint32_t len1)
{
if (!((uint64_t)len1 == (uint64_t)0U))
Hacl_Impl_Poly1305_64_poly1305_process_last_block(st, m, (uint64_t)len1);
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *h = scrut.h;
uint64_t *acc = h;
Hacl_Impl_Poly1305_64_poly1305_last_pass(acc);
}
void
Hacl_Poly1305_64_finish(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *mac,
uint8_t *k1)
{
Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
uint64_t *h = scrut.h;
uint64_t *acc = h;
FStar_UInt128_t k_ = load128_le(k1);
uint64_t h0 = acc[0U];
uint64_t h1 = acc[1U];
uint64_t h2 = acc[2U];
FStar_UInt128_t
acc_ =
FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128(h2
<< (uint32_t)24U |
h1 >> (uint32_t)20U),
(uint32_t)64U),
FStar_UInt128_uint64_to_uint128(h1 << (uint32_t)44U | h0));
FStar_UInt128_t mac_ = FStar_UInt128_add_mod(acc_, k_);
store128_le(mac, mac_);
}
void
Hacl_Poly1305_64_crypto_onetimeauth(
uint8_t *output,
uint8_t *input,
uint64_t len1,
uint8_t *k1)
{
Hacl_Standalone_Poly1305_64_crypto_onetimeauth(output, input, len1, k1);
}

View file

@ -0,0 +1,99 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kremlib.h"
#ifndef __Hacl_Poly1305_64_H
#define __Hacl_Poly1305_64_H
typedef uint64_t Hacl_Bignum_Constants_limb;
typedef FStar_UInt128_t Hacl_Bignum_Constants_wide;
typedef FStar_UInt128_t Hacl_Bignum_Wide_t;
typedef uint64_t Hacl_Bignum_Limb_t;
typedef void *Hacl_Impl_Poly1305_64_State_log_t;
typedef uint8_t *Hacl_Impl_Poly1305_64_State_uint8_p;
typedef uint64_t *Hacl_Impl_Poly1305_64_State_bigint;
typedef void *Hacl_Impl_Poly1305_64_State_seqelem;
typedef uint64_t *Hacl_Impl_Poly1305_64_State_elemB;
typedef uint8_t *Hacl_Impl_Poly1305_64_State_wordB;
typedef uint8_t *Hacl_Impl_Poly1305_64_State_wordB_16;
typedef struct
{
uint64_t *r;
uint64_t *h;
} Hacl_Impl_Poly1305_64_State_poly1305_state;
typedef void *Hacl_Impl_Poly1305_64_log_t;
typedef uint64_t *Hacl_Impl_Poly1305_64_bigint;
typedef uint8_t *Hacl_Impl_Poly1305_64_uint8_p;
typedef uint64_t *Hacl_Impl_Poly1305_64_elemB;
typedef uint8_t *Hacl_Impl_Poly1305_64_wordB;
typedef uint8_t *Hacl_Impl_Poly1305_64_wordB_16;
typedef uint8_t *Hacl_Poly1305_64_uint8_p;
typedef uint64_t Hacl_Poly1305_64_uint64_t;
typedef uint8_t *Hacl_Poly1305_64_key;
typedef Hacl_Impl_Poly1305_64_State_poly1305_state Hacl_Poly1305_64_state;
Hacl_Impl_Poly1305_64_State_poly1305_state
Hacl_Poly1305_64_mk_state(uint64_t *r, uint64_t *acc);
void Hacl_Poly1305_64_init(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *k1);
void Hacl_Poly1305_64_update_block(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *m);
void
Hacl_Poly1305_64_update(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint32_t num_blocks);
void
Hacl_Poly1305_64_update_last(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *m,
uint32_t len1);
void
Hacl_Poly1305_64_finish(
Hacl_Impl_Poly1305_64_State_poly1305_state st,
uint8_t *mac,
uint8_t *k1);
void
Hacl_Poly1305_64_crypto_onetimeauth(
uint8_t *output,
uint8_t *input,
uint64_t len1,
uint8_t *k1);
#endif

View file

@ -0,0 +1,672 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __KREMLIB_H
#define __KREMLIB_H
#include "kremlib_base.h"
/* For tests only: we might need this function to be forward-declared, because
* the dependency on WasmSupport appears very late, after SimplifyWasm, and
* sadly, after the topological order has been done. */
void WasmSupport_check_buffer_size(uint32_t s);
/******************************************************************************/
/* Stubs to ease compilation of non-Low* code */
/******************************************************************************/
/* Some types that KreMLin has no special knowledge of; many of them appear in
* signatures of ghost functions, meaning that it suffices to give them (any)
* definition. */
typedef void *FStar_Seq_Base_seq, *Prims_prop, *FStar_HyperStack_mem,
*FStar_Set_set, *Prims_st_pre_h, *FStar_Heap_heap, *Prims_all_pre_h,
*FStar_TSet_set, *Prims_list, *FStar_Map_t, *FStar_UInt63_t_,
*FStar_Int63_t_, *FStar_UInt63_t, *FStar_Int63_t, *FStar_UInt_uint_t,
*FStar_Int_int_t, *FStar_HyperStack_stackref, *FStar_Bytes_bytes,
*FStar_HyperHeap_rid, *FStar_Heap_aref, *FStar_Monotonic_Heap_heap,
*FStar_Monotonic_Heap_aref, *FStar_Monotonic_HyperHeap_rid,
*FStar_Monotonic_HyperStack_mem, *FStar_Char_char_;
typedef const char *Prims_string;
/* For "bare" targets that do not have a C stdlib, the user might want to use
* [-add-include '"mydefinitions.h"'] and override these. */
#ifndef KRML_HOST_PRINTF
#define KRML_HOST_PRINTF printf
#endif
#ifndef KRML_HOST_EXIT
#define KRML_HOST_EXIT exit
#endif
#ifndef KRML_HOST_MALLOC
#define KRML_HOST_MALLOC malloc
#endif
/* In statement position, exiting is easy. */
#define KRML_EXIT \
do { \
KRML_HOST_PRINTF("Unimplemented function at %s:%d\n", __FILE__, __LINE__); \
KRML_HOST_EXIT(254); \
} while (0)
/* In expression position, use the comma-operator and a malloc to return an
* expression of the right size. KreMLin passes t as the parameter to the macro.
*/
#define KRML_EABORT(t, msg) \
(KRML_HOST_PRINTF("KreMLin abort at %s:%d\n%s\n", __FILE__, __LINE__, msg), \
KRML_HOST_EXIT(255), *((t *)KRML_HOST_MALLOC(sizeof(t))))
/* In FStar.Buffer.fst, the size of arrays is uint32_t, but it's a number of
* *elements*. Do an ugly, run-time check (some of which KreMLin can eliminate).
*/
#define KRML_CHECK_SIZE(elt, size) \
if (((size_t)size) > SIZE_MAX / sizeof(elt)) { \
KRML_HOST_PRINTF( \
"Maximum allocatable size exceeded, aborting before overflow at " \
"%s:%d\n", \
__FILE__, __LINE__); \
KRML_HOST_EXIT(253); \
}
/* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls]
* option). Useful when trying to debug, say, Wasm, to compare traces. */
/* clang-format off */
#ifdef __GNUC__
#define KRML_FORMAT(X) _Generic((X), \
uint8_t : "0x%08" PRIx8, \
uint16_t: "0x%08" PRIx16, \
uint32_t: "0x%08" PRIx32, \
uint64_t: "0x%08" PRIx64, \
int8_t : "0x%08" PRIx8, \
int16_t : "0x%08" PRIx16, \
int32_t : "0x%08" PRIx32, \
int64_t : "0x%08" PRIx64, \
default : "%s")
#define KRML_FORMAT_ARG(X) _Generic((X), \
uint8_t : X, \
uint16_t: X, \
uint32_t: X, \
uint64_t: X, \
int8_t : X, \
int16_t : X, \
int32_t : X, \
int64_t : X, \
default : "unknown")
/* clang-format on */
#define KRML_DEBUG_RETURN(X) \
({ \
__auto_type _ret = (X); \
KRML_HOST_PRINTF("returning: "); \
KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret)); \
KRML_HOST_PRINTF(" \n"); \
_ret; \
})
#endif
#define FStar_Buffer_eqb(b1, b2, n) \
(memcmp((b1), (b2), (n) * sizeof((b1)[0])) == 0)
/* Stubs to make ST happy. Important note: you must generate a use of the macro
* argument, otherwise, you may have FStar_ST_recall(f) as the only use of f;
* KreMLin will think that this is a valid use, but then the C compiler, after
* macro expansion, will error out. */
#define FStar_HyperHeap_root 0
#define FStar_Pervasives_Native_fst(x) (x).fst
#define FStar_Pervasives_Native_snd(x) (x).snd
#define FStar_Seq_Base_createEmpty(x) 0
#define FStar_Seq_Base_create(len, init) 0
#define FStar_Seq_Base_upd(s, i, e) 0
#define FStar_Seq_Base_eq(l1, l2) 0
#define FStar_Seq_Base_length(l1) 0
#define FStar_Seq_Base_append(x, y) 0
#define FStar_Seq_Base_slice(x, y, z) 0
#define FStar_Seq_Properties_snoc(x, y) 0
#define FStar_Seq_Properties_cons(x, y) 0
#define FStar_Seq_Base_index(x, y) 0
#define FStar_HyperStack_is_eternal_color(x) 0
#define FStar_Monotonic_HyperHeap_root 0
#define FStar_Buffer_to_seq_full(x) 0
#define FStar_Buffer_recall(x)
#define FStar_HyperStack_ST_op_Colon_Equals(x, v) KRML_EXIT
#define FStar_HyperStack_ST_op_Bang(x) 0
#define FStar_HyperStack_ST_salloc(x) 0
#define FStar_HyperStack_ST_ralloc(x, y) 0
#define FStar_HyperStack_ST_new_region(x) (0)
#define FStar_Monotonic_RRef_m_alloc(x) \
{ \
0 \
}
#define FStar_HyperStack_ST_recall(x) \
do { \
(void)(x); \
} while (0)
#define FStar_HyperStack_ST_recall_region(x) \
do { \
(void)(x); \
} while (0)
#define FStar_Monotonic_RRef_m_recall(x1, x2) \
do { \
(void)(x1); \
(void)(x2); \
} while (0)
#define FStar_Monotonic_RRef_m_write(x1, x2, x3, x4, x5) \
do { \
(void)(x1); \
(void)(x2); \
(void)(x3); \
(void)(x4); \
(void)(x5); \
} while (0)
/******************************************************************************/
/* Endian-ness macros that can only be implemented in C */
/******************************************************************************/
/* ... for Linux */
#if defined(__linux__) || defined(__CYGWIN__)
#include <endian.h>
/* ... for OSX */
#elif defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#define htole64(x) OSSwapHostToLittleInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#define htobe64(x) OSSwapHostToBigInt64(x)
#define be64toh(x) OSSwapBigToHostInt64(x)
#define htole16(x) OSSwapHostToLittleInt16(x)
#define le16toh(x) OSSwapLittleToHostInt16(x)
#define htobe16(x) OSSwapHostToBigInt16(x)
#define be16toh(x) OSSwapBigToHostInt16(x)
#define htole32(x) OSSwapHostToLittleInt32(x)
#define le32toh(x) OSSwapLittleToHostInt32(x)
#define htobe32(x) OSSwapHostToBigInt32(x)
#define be32toh(x) OSSwapBigToHostInt32(x)
/* ... for Solaris */
#elif defined(__sun__)
#include <sys/byteorder.h>
#define htole64(x) LE_64(x)
#define le64toh(x) LE_64(x)
#define htobe64(x) BE_64(x)
#define be64toh(x) BE_64(x)
#define htole16(x) LE_16(x)
#define le16toh(x) LE_16(x)
#define htobe16(x) BE_16(x)
#define be16toh(x) BE_16(x)
#define htole32(x) LE_32(x)
#define le32toh(x) LE_32(x)
#define htobe32(x) BE_32(x)
#define be32toh(x) BE_32(x)
/* ... for the BSDs */
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#include <sys/endian.h>
#elif defined(__OpenBSD__)
#include <endian.h>
/* ... for Windows (MSVC)... not targeting XBOX 360! */
#elif defined(_MSC_VER)
#include <stdlib.h>
#define htobe16(x) _byteswap_ushort(x)
#define htole16(x) (x)
#define be16toh(x) _byteswap_ushort(x)
#define le16toh(x) (x)
#define htobe32(x) _byteswap_ulong(x)
#define htole32(x) (x)
#define be32toh(x) _byteswap_ulong(x)
#define le32toh(x) (x)
#define htobe64(x) _byteswap_uint64(x)
#define htole64(x) (x)
#define be64toh(x) _byteswap_uint64(x)
#define le64toh(x) (x)
/* ... for Windows (GCC-like, e.g. mingw or clang) */
#elif (defined(_WIN32) || defined(_WIN64)) && \
(defined(__GNUC__) || defined(__clang__))
#define htobe16(x) __builtin_bswap16(x)
#define htole16(x) (x)
#define be16toh(x) __builtin_bswap16(x)
#define le16toh(x) (x)
#define htobe32(x) __builtin_bswap32(x)
#define htole32(x) (x)
#define be32toh(x) __builtin_bswap32(x)
#define le32toh(x) (x)
#define htobe64(x) __builtin_bswap64(x)
#define htole64(x) (x)
#define be64toh(x) __builtin_bswap64(x)
#define le64toh(x) (x)
/* ... generic big-endian fallback code */
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* byte swapping code inspired by:
* https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h
* */
#define htobe32(x) (x)
#define be32toh(x) (x)
#define htole32(x) \
(__extension__({ \
uint32_t _temp = (x); \
((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
}))
#define le32toh(x) (htole32((x)))
#define htobe64(x) (x)
#define be64toh(x) (x)
#define htole64(x) \
(__extension__({ \
uint64_t __temp = (x); \
uint32_t __low = htobe32((uint32_t)__temp); \
uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
(((uint64_t)__low) << 32) | __high; \
}))
#define le64toh(x) (htole64((x)))
/* ... generic little-endian fallback code */
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define htole32(x) (x)
#define le32toh(x) (x)
#define htobe32(x) \
(__extension__({ \
uint32_t _temp = (x); \
((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
}))
#define be32toh(x) (htobe32((x)))
#define htole64(x) (x)
#define le64toh(x) (x)
#define htobe64(x) \
(__extension__({ \
uint64_t __temp = (x); \
uint32_t __low = htobe32((uint32_t)__temp); \
uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
(((uint64_t)__low) << 32) | __high; \
}))
#define be64toh(x) (htobe64((x)))
/* ... couldn't determine endian-ness of the target platform */
#else
#error "Please define __BYTE_ORDER__!"
#endif /* defined(__linux__) || ... */
/* Loads and stores. These avoid undefined behavior due to unaligned memory
* accesses, via memcpy. */
inline static uint16_t
load16(uint8_t *b)
{
uint16_t x;
memcpy(&x, b, 2);
return x;
}
inline static uint32_t
load32(uint8_t *b)
{
uint32_t x;
memcpy(&x, b, 4);
return x;
}
inline static uint64_t
load64(uint8_t *b)
{
uint64_t x;
memcpy(&x, b, 8);
return x;
}
inline static void
store16(uint8_t *b, uint16_t i)
{
memcpy(b, &i, 2);
}
inline static void
store32(uint8_t *b, uint32_t i)
{
memcpy(b, &i, 4);
}
inline static void
store64(uint8_t *b, uint64_t i)
{
memcpy(b, &i, 8);
}
#define load16_le(b) (le16toh(load16(b)))
#define store16_le(b, i) (store16(b, htole16(i)))
#define load16_be(b) (be16toh(load16(b)))
#define store16_be(b, i) (store16(b, htobe16(i)))
#define load32_le(b) (le32toh(load32(b)))
#define store32_le(b, i) (store32(b, htole32(i)))
#define load32_be(b) (be32toh(load32(b)))
#define store32_be(b, i) (store32(b, htobe32(i)))
#define load64_le(b) (le64toh(load64(b)))
#define store64_le(b, i) (store64(b, htole64(i)))
#define load64_be(b) (be64toh(load64(b)))
#define store64_be(b, i) (store64(b, htobe64(i)))
/******************************************************************************/
/* Checked integers to ease the compilation of non-Low* code */
/******************************************************************************/
typedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int,
krml_checked_int_t;
inline static bool
Prims_op_GreaterThanOrEqual(int32_t x, int32_t y)
{
return x >= y;
}
inline static bool
Prims_op_LessThanOrEqual(int32_t x, int32_t y)
{
return x <= y;
}
inline static bool
Prims_op_GreaterThan(int32_t x, int32_t y)
{
return x > y;
}
inline static bool
Prims_op_LessThan(int32_t x, int32_t y)
{
return x < y;
}
#define RETURN_OR(x) \
do { \
int64_t __ret = x; \
if (__ret < INT32_MIN || INT32_MAX < __ret) { \
KRML_HOST_PRINTF("Prims.{int,nat,pos} integer overflow at %s:%d\n", \
__FILE__, __LINE__); \
KRML_HOST_EXIT(252); \
} \
return (int32_t)__ret; \
} while (0)
inline static int32_t
Prims_pow2(int32_t x)
{
RETURN_OR((int64_t)1 << (int64_t)x);
}
inline static int32_t
Prims_op_Multiply(int32_t x, int32_t y)
{
RETURN_OR((int64_t)x * (int64_t)y);
}
inline static int32_t
Prims_op_Addition(int32_t x, int32_t y)
{
RETURN_OR((int64_t)x + (int64_t)y);
}
inline static int32_t
Prims_op_Subtraction(int32_t x, int32_t y)
{
RETURN_OR((int64_t)x - (int64_t)y);
}
inline static int32_t
Prims_op_Division(int32_t x, int32_t y)
{
RETURN_OR((int64_t)x / (int64_t)y);
}
inline static int32_t
Prims_op_Modulus(int32_t x, int32_t y)
{
RETURN_OR((int64_t)x % (int64_t)y);
}
inline static int8_t
FStar_UInt8_uint_to_t(int8_t x)
{
return x;
}
inline static int16_t
FStar_UInt16_uint_to_t(int16_t x)
{
return x;
}
inline static int32_t
FStar_UInt32_uint_to_t(int32_t x)
{
return x;
}
inline static int64_t
FStar_UInt64_uint_to_t(int64_t x)
{
return x;
}
inline static int8_t
FStar_UInt8_v(int8_t x)
{
return x;
}
inline static int16_t
FStar_UInt16_v(int16_t x)
{
return x;
}
inline static int32_t
FStar_UInt32_v(int32_t x)
{
return x;
}
inline static int64_t
FStar_UInt64_v(int64_t x)
{
return x;
}
/* Platform-specific 128-bit arithmetic. These are static functions in a header,
* so that each translation unit gets its own copy and the C compiler can
* optimize. */
#ifndef KRML_NOUINT128
typedef unsigned __int128 FStar_UInt128_t, FStar_UInt128_t_, uint128_t;
static inline void
print128(const char *where, uint128_t n)
{
KRML_HOST_PRINTF("%s: [%" PRIu64 ",%" PRIu64 "]\n", where,
(uint64_t)(n >> 64), (uint64_t)n);
}
static inline uint128_t
load128_le(uint8_t *b)
{
uint128_t l = (uint128_t)load64_le(b);
uint128_t h = (uint128_t)load64_le(b + 8);
return (h << 64 | l);
}
static inline void
store128_le(uint8_t *b, uint128_t n)
{
store64_le(b, (uint64_t)n);
store64_le(b + 8, (uint64_t)(n >> 64));
}
static inline uint128_t
load128_be(uint8_t *b)
{
uint128_t h = (uint128_t)load64_be(b);
uint128_t l = (uint128_t)load64_be(b + 8);
return (h << 64 | l);
}
static inline void
store128_be(uint8_t *b, uint128_t n)
{
store64_be(b, (uint64_t)(n >> 64));
store64_be(b + 8, (uint64_t)n);
}
#define FStar_UInt128_add(x, y) ((x) + (y))
#define FStar_UInt128_mul(x, y) ((x) * (y))
#define FStar_UInt128_add_mod(x, y) ((x) + (y))
#define FStar_UInt128_sub(x, y) ((x) - (y))
#define FStar_UInt128_sub_mod(x, y) ((x) - (y))
#define FStar_UInt128_logand(x, y) ((x) & (y))
#define FStar_UInt128_logor(x, y) ((x) | (y))
#define FStar_UInt128_logxor(x, y) ((x) ^ (y))
#define FStar_UInt128_lognot(x) (~(x))
#define FStar_UInt128_shift_left(x, y) ((x) << (y))
#define FStar_UInt128_shift_right(x, y) ((x) >> (y))
#define FStar_UInt128_uint64_to_uint128(x) ((uint128_t)(x))
#define FStar_UInt128_uint128_to_uint64(x) ((uint64_t)(x))
#define FStar_UInt128_mul_wide(x, y) ((uint128_t)(x) * (y))
#define FStar_UInt128_op_Hat_Hat(x, y) ((x) ^ (y))
static inline uint128_t
FStar_UInt128_eq_mask(uint128_t x, uint128_t y)
{
uint64_t mask =
FStar_UInt64_eq_mask((uint64_t)(x >> 64), (uint64_t)(y >> 64)) &
FStar_UInt64_eq_mask(x, y);
return ((uint128_t)mask) << 64 | mask;
}
static inline uint128_t
FStar_UInt128_gte_mask(uint128_t x, uint128_t y)
{
uint64_t mask =
(FStar_UInt64_gte_mask(x >> 64, y >> 64) &
~(FStar_UInt64_eq_mask(x >> 64, y >> 64))) |
(FStar_UInt64_eq_mask(x >> 64, y >> 64) & FStar_UInt64_gte_mask(x, y));
return ((uint128_t)mask) << 64 | mask;
}
#else /* !defined(KRML_NOUINT128) */
/* This is a bad circular dependency... should fix it properly. */
#include "FStar.h"
typedef FStar_UInt128_uint128 FStar_UInt128_t_, uint128_t;
/* A series of definitions written using pointers. */
static inline void
print128_(const char *where, uint128_t *n)
{
KRML_HOST_PRINTF("%s: [0x%08" PRIx64 ",0x%08" PRIx64 "]\n", where, n->high, n->low);
}
static inline void
load128_le_(uint8_t *b, uint128_t *r)
{
r->low = load64_le(b);
r->high = load64_le(b + 8);
}
static inline void
store128_le_(uint8_t *b, uint128_t *n)
{
store64_le(b, n->low);
store64_le(b + 8, n->high);
}
static inline void
load128_be_(uint8_t *b, uint128_t *r)
{
r->high = load64_be(b);
r->low = load64_be(b + 8);
}
static inline void
store128_be_(uint8_t *b, uint128_t *n)
{
store64_be(b, n->high);
store64_be(b + 8, n->low);
}
#ifndef KRML_NOSTRUCT_PASSING
static inline void
print128(const char *where, uint128_t n)
{
print128_(where, &n);
}
static inline uint128_t
load128_le(uint8_t *b)
{
uint128_t r;
load128_le_(b, &r);
return r;
}
static inline void
store128_le(uint8_t *b, uint128_t n)
{
store128_le_(b, &n);
}
static inline uint128_t
load128_be(uint8_t *b)
{
uint128_t r;
load128_be_(b, &r);
return r;
}
static inline void
store128_be(uint8_t *b, uint128_t n)
{
store128_be_(b, &n);
}
#else /* !defined(KRML_STRUCT_PASSING) */
#define print128 print128_
#define load128_le load128_le_
#define store128_le store128_le_
#define load128_be load128_be_
#define store128_be store128_be_
#endif /* KRML_STRUCT_PASSING */
#endif /* KRML_UINT128 */
#endif /* __KREMLIB_H */

View file

@ -0,0 +1,191 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __KREMLIB_BASE_H
#define __KREMLIB_BASE_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/******************************************************************************/
/* Some macros to ease compatibility */
/******************************************************************************/
/* Define __cdecl and friends when using GCC, so that we can safely compile code
* that contains __cdecl on all platforms. Note that this is in a separate
* header so that Dafny-generated code can include just this file. */
#ifndef _MSC_VER
/* Use the gcc predefined macros if on a platform/architectures that set them.
* Otherwise define them to be empty. */
#ifndef __cdecl
#define __cdecl
#endif
#ifndef __stdcall
#define __stdcall
#endif
#ifndef __fastcall
#define __fastcall
#endif
#endif
#ifdef __GNUC__
#define inline __inline__
#endif
/* GCC-specific attribute syntax; everyone else gets the standard C inline
* attribute. */
#ifdef __GNU_C__
#ifndef __clang__
#define force_inline inline __attribute__((always_inline))
#else
#define force_inline inline
#endif
#else
#define force_inline inline
#endif
/******************************************************************************/
/* Implementing C.fst */
/******************************************************************************/
/* Uppercase issue; we have to define lowercase versions of the C macros (as we
* have no way to refer to an uppercase *variable* in F*). */
extern int exit_success;
extern int exit_failure;
/* This one allows the user to write C.EXIT_SUCCESS. */
typedef int exit_code;
void print_string(const char *s);
void print_bytes(uint8_t *b, uint32_t len);
/* The universal null pointer defined in C.Nullity.fst */
#define C_Nullity_null(X) 0
/* If some globals need to be initialized before the main, then kremlin will
* generate and try to link last a function with this type: */
void kremlinit_globals(void);
/******************************************************************************/
/* Implementation of machine integers (possibly of 128-bit integers) */
/******************************************************************************/
/* Integer types */
typedef uint64_t FStar_UInt64_t, FStar_UInt64_t_;
typedef int64_t FStar_Int64_t, FStar_Int64_t_;
typedef uint32_t FStar_UInt32_t, FStar_UInt32_t_;
typedef int32_t FStar_Int32_t, FStar_Int32_t_;
typedef uint16_t FStar_UInt16_t, FStar_UInt16_t_;
typedef int16_t FStar_Int16_t, FStar_Int16_t_;
typedef uint8_t FStar_UInt8_t, FStar_UInt8_t_;
typedef int8_t FStar_Int8_t, FStar_Int8_t_;
static inline uint32_t
rotate32_left(uint32_t x, uint32_t n)
{
/* assert (n<32); */
return (x << n) | (x >> (32 - n));
}
static inline uint32_t
rotate32_right(uint32_t x, uint32_t n)
{
/* assert (n<32); */
return (x >> n) | (x << (32 - n));
}
/* Constant time comparisons */
static inline uint8_t
FStar_UInt8_eq_mask(uint8_t x, uint8_t y)
{
x = ~(x ^ y);
x &= x << 4;
x &= x << 2;
x &= x << 1;
return (int8_t)x >> 7;
}
static inline uint8_t
FStar_UInt8_gte_mask(uint8_t x, uint8_t y)
{
return ~(uint8_t)(((int32_t)x - y) >> 31);
}
static inline uint16_t
FStar_UInt16_eq_mask(uint16_t x, uint16_t y)
{
x = ~(x ^ y);
x &= x << 8;
x &= x << 4;
x &= x << 2;
x &= x << 1;
return (int16_t)x >> 15;
}
static inline uint16_t
FStar_UInt16_gte_mask(uint16_t x, uint16_t y)
{
return ~(uint16_t)(((int32_t)x - y) >> 31);
}
static inline uint32_t
FStar_UInt32_eq_mask(uint32_t x, uint32_t y)
{
x = ~(x ^ y);
x &= x << 16;
x &= x << 8;
x &= x << 4;
x &= x << 2;
x &= x << 1;
return ((int32_t)x) >> 31;
}
static inline uint32_t
FStar_UInt32_gte_mask(uint32_t x, uint32_t y)
{
return ~((uint32_t)(((int64_t)x - y) >> 63));
}
static inline uint64_t
FStar_UInt64_eq_mask(uint64_t x, uint64_t y)
{
x = ~(x ^ y);
x &= x << 32;
x &= x << 16;
x &= x << 8;
x &= x << 4;
x &= x << 2;
x &= x << 1;
return ((int64_t)x) >> 63;
}
static inline uint64_t
FStar_UInt64_gte_mask(uint64_t x, uint64_t y)
{
uint64_t low63 =
~((uint64_t)((int64_t)((int64_t)(x & UINT64_C(0x7fffffffffffffff)) -
(int64_t)(y & UINT64_C(0x7fffffffffffffff))) >>
63));
uint64_t high_bit =
~((uint64_t)((int64_t)((int64_t)(x & UINT64_C(0x8000000000000000)) -
(int64_t)(y & UINT64_C(0x8000000000000000))) >>
63));
return low63 & high_bit;
}
#endif

View file

@ -0,0 +1,98 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module Spec.CTR
module ST = FStar.HyperStack.ST
open FStar.Mul
open FStar.Seq
open Spec.Lib
#reset-options "--initial_fuel 0 --max_fuel 0 --initial_ifuel 0 --max_ifuel 0"
type block_cipher_ctx = {
keylen: nat ;
blocklen: (x:nat{x>0});
noncelen: nat;
counterbits: nat;
incr: pos}
type key (c:block_cipher_ctx) = lbytes c.keylen
type nonce (c:block_cipher_ctx) = lbytes c.noncelen
type block (c:block_cipher_ctx) = lbytes (c.blocklen*c.incr)
type counter (c:block_cipher_ctx) = UInt.uint_t c.counterbits
type block_cipher (c:block_cipher_ctx) = key c -> nonce c -> counter c -> block c
val xor: #len:nat -> x:lbytes len -> y:lbytes len -> Tot (lbytes len)
let xor #len x y = map2 FStar.UInt8.(fun x y -> x ^^ y) x y
val counter_mode_blocks:
ctx: block_cipher_ctx ->
bc: block_cipher ctx ->
k:key ctx -> n:nonce ctx -> c:counter ctx ->
plain:seq UInt8.t{c + ctx.incr * (length plain / ctx.blocklen) < pow2 ctx.counterbits /\
length plain % (ctx.blocklen * ctx.incr) = 0} ->
Tot (lbytes (length plain))
(decreases (length plain))
#reset-options "--z3rlimit 200 --max_fuel 0"
let rec counter_mode_blocks ctx block_enc key nonce counter plain =
let len = length plain in
let len' = len / (ctx.blocklen * ctx.incr) in
Math.Lemmas.lemma_div_mod len (ctx.blocklen * ctx.incr) ;
if len = 0 then Seq.createEmpty #UInt8.t
else (
let prefix, block = split plain (len - ctx.blocklen * ctx.incr) in
(* TODO: move to a single lemma for clarify *)
Math.Lemmas.lemma_mod_plus (length prefix) 1 (ctx.blocklen * ctx.incr);
Math.Lemmas.lemma_div_le (length prefix) len ctx.blocklen;
Spec.CTR.Lemmas.lemma_div len (ctx.blocklen * ctx.incr);
(* End TODO *)
let cipher = counter_mode_blocks ctx block_enc key nonce counter prefix in
let mask = block_enc key nonce (counter + (len / ctx.blocklen - 1) * ctx.incr) in
let eb = xor block mask in
cipher @| eb
)
val counter_mode:
ctx: block_cipher_ctx ->
bc: block_cipher ctx ->
k:key ctx -> n:nonce ctx -> c:counter ctx ->
plain:seq UInt8.t{c + ctx.incr * (length plain / ctx.blocklen) < pow2 ctx.counterbits} ->
Tot (lbytes (length plain))
(decreases (length plain))
#reset-options "--z3rlimit 200 --max_fuel 0"
let counter_mode ctx block_enc key nonce counter plain =
let len = length plain in
let blocks_len = (ctx.incr * ctx.blocklen) * (len / (ctx.blocklen * ctx.incr)) in
let part_len = len % (ctx.blocklen * ctx.incr) in
(* TODO: move to a single lemma for clarify *)
Math.Lemmas.lemma_div_mod len (ctx.blocklen * ctx.incr);
Math.Lemmas.multiple_modulo_lemma (len / (ctx.blocklen * ctx.incr)) (ctx.blocklen * ctx.incr);
Math.Lemmas.lemma_div_le (blocks_len) len ctx.blocklen;
(* End TODO *)
let blocks, last_block = split plain blocks_len in
let cipher_blocks = counter_mode_blocks ctx block_enc key nonce counter blocks in
let cipher_last_block =
if part_len > 0
then (* encrypt final partial block(s) *)
let mask = block_enc key nonce (counter+ctx.incr*(length plain / ctx.blocklen)) in
let mask = slice mask 0 part_len in
assert(length last_block = part_len);
xor #part_len last_block mask
else createEmpty in
cipher_blocks @| cipher_last_block

View file

@ -0,0 +1,169 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module Spec.Chacha20
module ST = FStar.HyperStack.ST
open FStar.Mul
open FStar.Seq
open FStar.UInt32
open FStar.Endianness
open Spec.Lib
open Spec.Chacha20.Lemmas
open Seq.Create
#set-options "--max_fuel 0 --z3rlimit 100"
(* Constants *)
let keylen = 32 (* in bytes *)
let blocklen = 64 (* in bytes *)
let noncelen = 12 (* in bytes *)
type key = lbytes keylen
type block = lbytes blocklen
type nonce = lbytes noncelen
type counter = UInt.uint_t 32
// using @ as a functional substitute for ;
// internally, blocks are represented as 16 x 4-byte integers
type state = m:seq UInt32.t {length m = 16}
type idx = n:nat{n < 16}
type shuffle = state -> Tot state
let line (a:idx) (b:idx) (d:idx) (s:t{0 < v s /\ v s < 32}) (m:state) : Tot state =
let m = m.[a] <- (m.[a] +%^ m.[b]) in
let m = m.[d] <- ((m.[d] ^^ m.[a]) <<< s) in m
let quarter_round a b c d : shuffle =
line a b d 16ul @
line c d b 12ul @
line a b d 8ul @
line c d b 7ul
let column_round : shuffle =
quarter_round 0 4 8 12 @
quarter_round 1 5 9 13 @
quarter_round 2 6 10 14 @
quarter_round 3 7 11 15
let diagonal_round : shuffle =
quarter_round 0 5 10 15 @
quarter_round 1 6 11 12 @
quarter_round 2 7 8 13 @
quarter_round 3 4 9 14
let double_round: shuffle =
column_round @ diagonal_round (* 2 rounds *)
let rounds : shuffle =
iter 10 double_round (* 20 rounds *)
let chacha20_core (s:state) : Tot state =
let s' = rounds s in
Spec.Loops.seq_map2 (fun x y -> x +%^ y) s' s
(* state initialization *)
let c0 = 0x61707865ul
let c1 = 0x3320646eul
let c2 = 0x79622d32ul
let c3 = 0x6b206574ul
let setup (k:key) (n:nonce) (c:counter): Tot state =
create_4 c0 c1 c2 c3 @|
uint32s_from_le 8 k @|
create_1 (UInt32.uint_to_t c) @|
uint32s_from_le 3 n
let chacha20_block (k:key) (n:nonce) (c:counter): Tot block =
let st = setup k n c in
let st' = chacha20_core st in
uint32s_to_le 16 st'
let chacha20_ctx: Spec.CTR.block_cipher_ctx =
let open Spec.CTR in
{
keylen = keylen;
blocklen = blocklen;
noncelen = noncelen;
counterbits = 32;
incr = 1
}
let chacha20_cipher: Spec.CTR.block_cipher chacha20_ctx = chacha20_block
let chacha20_encrypt_bytes key nonce counter m =
Spec.CTR.counter_mode chacha20_ctx chacha20_cipher key nonce counter m
unfold let test_plaintext = [
0x4cuy; 0x61uy; 0x64uy; 0x69uy; 0x65uy; 0x73uy; 0x20uy; 0x61uy;
0x6euy; 0x64uy; 0x20uy; 0x47uy; 0x65uy; 0x6euy; 0x74uy; 0x6cuy;
0x65uy; 0x6duy; 0x65uy; 0x6euy; 0x20uy; 0x6fuy; 0x66uy; 0x20uy;
0x74uy; 0x68uy; 0x65uy; 0x20uy; 0x63uy; 0x6cuy; 0x61uy; 0x73uy;
0x73uy; 0x20uy; 0x6fuy; 0x66uy; 0x20uy; 0x27uy; 0x39uy; 0x39uy;
0x3auy; 0x20uy; 0x49uy; 0x66uy; 0x20uy; 0x49uy; 0x20uy; 0x63uy;
0x6fuy; 0x75uy; 0x6cuy; 0x64uy; 0x20uy; 0x6fuy; 0x66uy; 0x66uy;
0x65uy; 0x72uy; 0x20uy; 0x79uy; 0x6fuy; 0x75uy; 0x20uy; 0x6fuy;
0x6euy; 0x6cuy; 0x79uy; 0x20uy; 0x6fuy; 0x6euy; 0x65uy; 0x20uy;
0x74uy; 0x69uy; 0x70uy; 0x20uy; 0x66uy; 0x6fuy; 0x72uy; 0x20uy;
0x74uy; 0x68uy; 0x65uy; 0x20uy; 0x66uy; 0x75uy; 0x74uy; 0x75uy;
0x72uy; 0x65uy; 0x2cuy; 0x20uy; 0x73uy; 0x75uy; 0x6euy; 0x73uy;
0x63uy; 0x72uy; 0x65uy; 0x65uy; 0x6euy; 0x20uy; 0x77uy; 0x6fuy;
0x75uy; 0x6cuy; 0x64uy; 0x20uy; 0x62uy; 0x65uy; 0x20uy; 0x69uy;
0x74uy; 0x2euy
]
unfold let test_ciphertext = [
0x6euy; 0x2euy; 0x35uy; 0x9auy; 0x25uy; 0x68uy; 0xf9uy; 0x80uy;
0x41uy; 0xbauy; 0x07uy; 0x28uy; 0xdduy; 0x0duy; 0x69uy; 0x81uy;
0xe9uy; 0x7euy; 0x7auy; 0xecuy; 0x1duy; 0x43uy; 0x60uy; 0xc2uy;
0x0auy; 0x27uy; 0xafuy; 0xccuy; 0xfduy; 0x9fuy; 0xaeuy; 0x0buy;
0xf9uy; 0x1buy; 0x65uy; 0xc5uy; 0x52uy; 0x47uy; 0x33uy; 0xabuy;
0x8fuy; 0x59uy; 0x3duy; 0xabuy; 0xcduy; 0x62uy; 0xb3uy; 0x57uy;
0x16uy; 0x39uy; 0xd6uy; 0x24uy; 0xe6uy; 0x51uy; 0x52uy; 0xabuy;
0x8fuy; 0x53uy; 0x0cuy; 0x35uy; 0x9fuy; 0x08uy; 0x61uy; 0xd8uy;
0x07uy; 0xcauy; 0x0duy; 0xbfuy; 0x50uy; 0x0duy; 0x6auy; 0x61uy;
0x56uy; 0xa3uy; 0x8euy; 0x08uy; 0x8auy; 0x22uy; 0xb6uy; 0x5euy;
0x52uy; 0xbcuy; 0x51uy; 0x4duy; 0x16uy; 0xccuy; 0xf8uy; 0x06uy;
0x81uy; 0x8cuy; 0xe9uy; 0x1auy; 0xb7uy; 0x79uy; 0x37uy; 0x36uy;
0x5auy; 0xf9uy; 0x0buy; 0xbfuy; 0x74uy; 0xa3uy; 0x5buy; 0xe6uy;
0xb4uy; 0x0buy; 0x8euy; 0xeduy; 0xf2uy; 0x78uy; 0x5euy; 0x42uy;
0x87uy; 0x4duy
]
unfold let test_key = [
0uy; 1uy; 2uy; 3uy; 4uy; 5uy; 6uy; 7uy;
8uy; 9uy; 10uy; 11uy; 12uy; 13uy; 14uy; 15uy;
16uy; 17uy; 18uy; 19uy; 20uy; 21uy; 22uy; 23uy;
24uy; 25uy; 26uy; 27uy; 28uy; 29uy; 30uy; 31uy
]
unfold let test_nonce = [
0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0x4auy; 0uy; 0uy; 0uy; 0uy
]
unfold let test_counter = 1
let test() =
assert_norm(List.Tot.length test_plaintext = 114);
assert_norm(List.Tot.length test_ciphertext = 114);
assert_norm(List.Tot.length test_key = 32);
assert_norm(List.Tot.length test_nonce = 12);
let test_plaintext = createL test_plaintext in
let test_ciphertext = createL test_ciphertext in
let test_key = createL test_key in
let test_nonce = createL test_nonce in
chacha20_encrypt_bytes test_key test_nonce test_counter test_plaintext
= test_ciphertext

View file

@ -0,0 +1,168 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module Spec.Curve25519
module ST = FStar.HyperStack.ST
open FStar.Mul
open FStar.Seq
open FStar.UInt8
open FStar.Endianness
open Spec.Lib
open Spec.Curve25519.Lemmas
#reset-options "--initial_fuel 0 --max_fuel 0 --z3rlimit 20"
(* Field types and parameters *)
let prime = pow2 255 - 19
type elem : Type0 = e:int{e >= 0 /\ e < prime}
let fadd e1 e2 = (e1 + e2) % prime
let fsub e1 e2 = (e1 - e2) % prime
let fmul e1 e2 = (e1 * e2) % prime
let zero : elem = 0
let one : elem = 1
let ( +@ ) = fadd
let ( *@ ) = fmul
(** Exponentiation *)
let rec ( ** ) (e:elem) (n:pos) : Tot elem (decreases n) =
if n = 1 then e
else
if n % 2 = 0 then op_Star_Star (e `fmul` e) (n / 2)
else e `fmul` (op_Star_Star (e `fmul` e) ((n-1)/2))
(* Type aliases *)
type scalar = lbytes 32
type serialized_point = lbytes 32
type proj_point = | Proj: x:elem -> z:elem -> proj_point
let decodeScalar25519 (k:scalar) =
let k = k.[0] <- (k.[0] &^ 248uy) in
let k = k.[31] <- ((k.[31] &^ 127uy) |^ 64uy) in k
let decodePoint (u:serialized_point) =
(little_endian u % pow2 255) % prime
let add_and_double qx nq nqp1 =
let x_1 = qx in
let x_2, z_2 = nq.x, nq.z in
let x_3, z_3 = nqp1.x, nqp1.z in
let a = x_2 `fadd` z_2 in
let aa = a**2 in
let b = x_2 `fsub` z_2 in
let bb = b**2 in
let e = aa `fsub` bb in
let c = x_3 `fadd` z_3 in
let d = x_3 `fsub` z_3 in
let da = d `fmul` a in
let cb = c `fmul` b in
let x_3 = (da `fadd` cb)**2 in
let z_3 = x_1 `fmul` ((da `fsub` cb)**2) in
let x_2 = aa `fmul` bb in
let z_2 = e `fmul` (aa `fadd` (121665 `fmul` e)) in
Proj x_2 z_2, Proj x_3 z_3
let ith_bit (k:scalar) (i:nat{i < 256}) =
let q = i / 8 in let r = i % 8 in
(v (k.[q]) / pow2 r) % 2
let rec montgomery_ladder_ (init:elem) x xp1 (k:scalar) (ctr:nat{ctr<=256})
: Tot proj_point (decreases ctr) =
if ctr = 0 then x
else (
let ctr' = ctr - 1 in
let (x', xp1') =
if ith_bit k ctr' = 1 then (
let nqp2, nqp1 = add_and_double init xp1 x in
nqp1, nqp2
) else add_and_double init x xp1 in
montgomery_ladder_ init x' xp1' k ctr'
)
let montgomery_ladder (init:elem) (k:scalar) : Tot proj_point =
montgomery_ladder_ init (Proj one zero) (Proj init one) k 256
let encodePoint (p:proj_point) : Tot serialized_point =
let p = p.x `fmul` (p.z ** (prime - 2)) in
little_bytes 32ul p
let scalarmult (k:scalar) (u:serialized_point) : Tot serialized_point =
let k = decodeScalar25519 k in
let u = decodePoint u in
let res = montgomery_ladder u k in
encodePoint res
(* ********************* *)
(* RFC 7748 Test Vectors *)
(* ********************* *)
let scalar1 = [
0xa5uy; 0x46uy; 0xe3uy; 0x6buy; 0xf0uy; 0x52uy; 0x7cuy; 0x9duy;
0x3buy; 0x16uy; 0x15uy; 0x4buy; 0x82uy; 0x46uy; 0x5euy; 0xdduy;
0x62uy; 0x14uy; 0x4cuy; 0x0auy; 0xc1uy; 0xfcuy; 0x5auy; 0x18uy;
0x50uy; 0x6auy; 0x22uy; 0x44uy; 0xbauy; 0x44uy; 0x9auy; 0xc4uy
]
let scalar2 = [
0x4buy; 0x66uy; 0xe9uy; 0xd4uy; 0xd1uy; 0xb4uy; 0x67uy; 0x3cuy;
0x5auy; 0xd2uy; 0x26uy; 0x91uy; 0x95uy; 0x7duy; 0x6auy; 0xf5uy;
0xc1uy; 0x1buy; 0x64uy; 0x21uy; 0xe0uy; 0xeauy; 0x01uy; 0xd4uy;
0x2cuy; 0xa4uy; 0x16uy; 0x9euy; 0x79uy; 0x18uy; 0xbauy; 0x0duy
]
let input1 = [
0xe6uy; 0xdbuy; 0x68uy; 0x67uy; 0x58uy; 0x30uy; 0x30uy; 0xdbuy;
0x35uy; 0x94uy; 0xc1uy; 0xa4uy; 0x24uy; 0xb1uy; 0x5fuy; 0x7cuy;
0x72uy; 0x66uy; 0x24uy; 0xecuy; 0x26uy; 0xb3uy; 0x35uy; 0x3buy;
0x10uy; 0xa9uy; 0x03uy; 0xa6uy; 0xd0uy; 0xabuy; 0x1cuy; 0x4cuy
]
let input2 = [
0xe5uy; 0x21uy; 0x0fuy; 0x12uy; 0x78uy; 0x68uy; 0x11uy; 0xd3uy;
0xf4uy; 0xb7uy; 0x95uy; 0x9duy; 0x05uy; 0x38uy; 0xaeuy; 0x2cuy;
0x31uy; 0xdbuy; 0xe7uy; 0x10uy; 0x6fuy; 0xc0uy; 0x3cuy; 0x3euy;
0xfcuy; 0x4cuy; 0xd5uy; 0x49uy; 0xc7uy; 0x15uy; 0xa4uy; 0x93uy
]
let expected1 = [
0xc3uy; 0xdauy; 0x55uy; 0x37uy; 0x9duy; 0xe9uy; 0xc6uy; 0x90uy;
0x8euy; 0x94uy; 0xeauy; 0x4duy; 0xf2uy; 0x8duy; 0x08uy; 0x4fuy;
0x32uy; 0xecuy; 0xcfuy; 0x03uy; 0x49uy; 0x1cuy; 0x71uy; 0xf7uy;
0x54uy; 0xb4uy; 0x07uy; 0x55uy; 0x77uy; 0xa2uy; 0x85uy; 0x52uy
]
let expected2 = [
0x95uy; 0xcbuy; 0xdeuy; 0x94uy; 0x76uy; 0xe8uy; 0x90uy; 0x7duy;
0x7auy; 0xaduy; 0xe4uy; 0x5cuy; 0xb4uy; 0xb8uy; 0x73uy; 0xf8uy;
0x8buy; 0x59uy; 0x5auy; 0x68uy; 0x79uy; 0x9fuy; 0xa1uy; 0x52uy;
0xe6uy; 0xf8uy; 0xf7uy; 0x64uy; 0x7auy; 0xacuy; 0x79uy; 0x57uy
]
let test () =
assert_norm(List.Tot.length scalar1 = 32);
assert_norm(List.Tot.length scalar2 = 32);
assert_norm(List.Tot.length input1 = 32);
assert_norm(List.Tot.length input2 = 32);
assert_norm(List.Tot.length expected1 = 32);
assert_norm(List.Tot.length expected2 = 32);
let scalar1 = createL scalar1 in
let scalar2 = createL scalar2 in
let input1 = createL input1 in
let input2 = createL input2 in
let expected1 = createL expected1 in
let expected2 = createL expected2 in
scalarmult scalar1 input1 = expected1
&& scalarmult scalar2 input2 = expected2

View file

@ -0,0 +1,107 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module Spec.Poly1305
module ST = FStar.HyperStack.ST
open FStar.Math.Lib
open FStar.Mul
open FStar.Seq
open FStar.UInt8
open FStar.Endianness
open Spec.Poly1305.Lemmas
#set-options "--initial_fuel 0 --max_fuel 0 --initial_ifuel 0 --max_ifuel 0"
(* Field types and parameters *)
let prime = pow2 130 - 5
type elem = e:int{e >= 0 /\ e < prime}
let fadd (e1:elem) (e2:elem) = (e1 + e2) % prime
let fmul (e1:elem) (e2:elem) = (e1 * e2) % prime
let zero : elem = 0
let one : elem = 1
let op_Plus_At = fadd
let op_Star_At = fmul
(* Type aliases *)
let op_Amp_Bar = UInt.logand #128
type word = w:bytes{length w <= 16}
type word_16 = w:bytes{length w = 16}
type tag = word_16
type key = lbytes 32
type text = seq word
(* Specification code *)
let encode (w:word) =
(pow2 (8 * length w)) `fadd` (little_endian w)
let rec poly (txt:text) (r:e:elem) : Tot elem (decreases (length txt)) =
if length txt = 0 then zero
else
let a = poly (Seq.tail txt) r in
let n = encode (Seq.head txt) in
(n `fadd` a) `fmul` r
let encode_r (rb:word_16) =
(little_endian rb) &| 0x0ffffffc0ffffffc0ffffffc0fffffff
let finish (a:elem) (s:word_16) : Tot tag =
let n = (a + little_endian s) % pow2 128 in
little_bytes 16ul n
let rec encode_bytes (txt:bytes) : Tot text (decreases (length txt)) =
if length txt = 0 then createEmpty
else
let w, txt = split txt (min (length txt) 16) in
append_last (encode_bytes txt) w
let poly1305 (msg:bytes) (k:key) : Tot tag =
let text = encode_bytes msg in
let r = encode_r (slice k 0 16) in
let s = slice k 16 32 in
finish (poly text r) s
(* ********************* *)
(* RFC 7539 Test Vectors *)
(* ********************* *)
#reset-options "--initial_fuel 0 --max_fuel 0 --z3rlimit 20"
unfold let msg = [
0x43uy; 0x72uy; 0x79uy; 0x70uy; 0x74uy; 0x6fuy; 0x67uy; 0x72uy;
0x61uy; 0x70uy; 0x68uy; 0x69uy; 0x63uy; 0x20uy; 0x46uy; 0x6fuy;
0x72uy; 0x75uy; 0x6duy; 0x20uy; 0x52uy; 0x65uy; 0x73uy; 0x65uy;
0x61uy; 0x72uy; 0x63uy; 0x68uy; 0x20uy; 0x47uy; 0x72uy; 0x6fuy;
0x75uy; 0x70uy ]
unfold let k = [
0x85uy; 0xd6uy; 0xbeuy; 0x78uy; 0x57uy; 0x55uy; 0x6duy; 0x33uy;
0x7fuy; 0x44uy; 0x52uy; 0xfeuy; 0x42uy; 0xd5uy; 0x06uy; 0xa8uy;
0x01uy; 0x03uy; 0x80uy; 0x8auy; 0xfbuy; 0x0duy; 0xb2uy; 0xfduy;
0x4auy; 0xbfuy; 0xf6uy; 0xafuy; 0x41uy; 0x49uy; 0xf5uy; 0x1buy ]
unfold let expected = [
0xa8uy; 0x06uy; 0x1duy; 0xc1uy; 0x30uy; 0x51uy; 0x36uy; 0xc6uy;
0xc2uy; 0x2buy; 0x8buy; 0xafuy; 0x0cuy; 0x01uy; 0x27uy; 0xa9uy ]
let test () : Tot bool =
assert_norm(List.Tot.length msg = 34);
assert_norm(List.Tot.length k = 32);
assert_norm(List.Tot.length expected = 16);
let msg = createL msg in
let k = createL k in
let expected = createL expected in
poly1305 msg k = expected

View file

@ -1115,3 +1115,21 @@ PK11_GetTokenURI;
;+ local:
;+ *;
;+};
;+NSS_3.33 { # NSS 3.33 release
;+ global:
CERT_FindCertByIssuerAndSNCX;
CERT_FindCertByNicknameOrEmailAddrCX;
CERT_FindCertByNicknameOrEmailAddrForUsageCX;
;+ local:
;+ *;
;+};
;+NSS_3.34 { # NSS 3.34 release
;+ global:
PK11_CreateManagedGenericObject;
SGN_NewContextWithAlgorithmID;
SEC_SignDataWithAlgorithmID;
SEC_DerSignDataWithAlgorithmID;
SEC_CreateSignatureAlgorithmParameters;
;+ local:
;+ *;
;+};

View file

@ -22,10 +22,10 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define NSS_VERSION "3.32.1" _NSS_CUSTOMIZED
#define NSS_VERSION "3.35" _NSS_CUSTOMIZED
#define NSS_VMAJOR 3
#define NSS_VMINOR 32
#define NSS_VPATCH 1
#define NSS_VMINOR 35
#define NSS_VPATCH 0
#define NSS_VBUILD 0
#define NSS_BETA PR_FALSE
@ -291,6 +291,15 @@ SECStatus NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData);
#define NSS_DTLS_VERSION_MIN_POLICY 0x00a
#define NSS_DTLS_VERSION_MAX_POLICY 0x00b
/* Until NSS 3.30, the PKCS#12 implementation used BMPString encoding
* for all passwords. This changed to use UTF-8 for non-PKCS#12 PBEs
* in NSS 3.31.
*
* For backward compatibility, this option reverts the behavior to the
* old NSS versions. This option might be removed in the future NSS
* releases; don't rely on it. */
#define __NSS_PKCS12_DECODE_FORCE_UNICODE 0x00c
/*
* Set and get global options for the NSS library.
*/

View file

@ -23,6 +23,7 @@ struct nssOps {
PRInt32 tlsVersionMaxPolicy;
PRInt32 dtlsVersionMinPolicy;
PRInt32 dtlsVersionMaxPolicy;
PRInt32 pkcs12DecodeForceUnicode;
};
static struct nssOps nss_ops = {
@ -33,6 +34,7 @@ static struct nssOps nss_ops = {
0xffff, /* set TLS max to more than the largest legal SSL value */
1,
0xffff,
PR_FALSE
};
SECStatus
@ -62,6 +64,9 @@ NSS_OptionSet(PRInt32 which, PRInt32 value)
case NSS_DTLS_VERSION_MAX_POLICY:
nss_ops.dtlsVersionMaxPolicy = value;
break;
case __NSS_PKCS12_DECODE_FORCE_UNICODE:
nss_ops.pkcs12DecodeForceUnicode = value;
break;
default:
rv = SECFailure;
}
@ -96,6 +101,9 @@ NSS_OptionGet(PRInt32 which, PRInt32 *value)
case NSS_DTLS_VERSION_MAX_POLICY:
*value = nss_ops.dtlsVersionMaxPolicy;
break;
case __NSS_PKCS12_DECODE_FORCE_UNICODE:
*value = nss_ops.pkcs12DecodeForceUnicode;
break;
default:
rv = SECFailure;
}

View file

@ -75,6 +75,8 @@
#undef PORT_UCS2_ASCIIConversion
#undef PORT_UCS2_UTF8Conversion
#undef PORT_ZAlloc
#undef PORT_ZAllocAligned
#undef PORT_ZAllocAlignedOffset
#undef PORT_ZFree
#undef SEC_ASN1Decode
#undef SEC_ASN1DecodeInteger
@ -144,6 +146,18 @@ PORT_ZAlloc(size_t bytes)
return PORT_ZAlloc_Util(bytes);
}
void *
PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem)
{
return PORT_ZAllocAligned_Util(bytes, alignment, mem);
}
void *
PORT_ZAllocAlignedOffset(size_t bytes, size_t alignment, size_t offset)
{
return PORT_ZAllocAlignedOffset_Util(bytes, alignment, offset);
}
void
PORT_Free(void *ptr)
{

View file

@ -64,8 +64,7 @@ secmodUnlockMutext(CK_VOID_PTR mutext)
static SECMODModuleID nextModuleID = 1;
static const CK_C_INITIALIZE_ARGS secmodLockFunctions = {
secmodCreateMutext, secmodDestroyMutext, secmodLockMutext,
secmodUnlockMutext, CKF_LIBRARY_CANT_CREATE_OS_THREADS |
CKF_OS_LOCKING_OK,
secmodUnlockMutext, CKF_LIBRARY_CANT_CREATE_OS_THREADS | CKF_OS_LOCKING_OK,
NULL
};
static const CK_C_INITIALIZE_ARGS secmodNoLockArgs = {

View file

@ -68,8 +68,11 @@ pk11_copyAttributes(PLArenaPool *arena,
copyTemplate, copyTemplateCount);
/* if we have missing attributes, just skip them and create the object */
if (crv == CKR_ATTRIBUTE_TYPE_INVALID) {
int i, j;
CK_ULONG i, j;
newTemplate = PORT_NewArray(CK_ATTRIBUTE, copyTemplateCount);
if (!newTemplate) {
return SECFailure;
}
/* remove the unknown attributes. If we don't have enough attributes
* PK11_CreateNewObject() will fail */
for (i = 0, j = 0; i < copyTemplateCount; i++) {
@ -1258,6 +1261,7 @@ pk11_newMergeLogNode(PLArenaPool *arena,
/* initialize it */
obj->slot = slot;
obj->objectID = id;
obj->owner = PR_FALSE;
newLog->object = obj;
newLog->error = error;

View file

@ -201,7 +201,6 @@ PK11_GetAttributes(PLArenaPool *arena, PK11SlotInfo *slot,
/* make pedantic happy... note that it's only used arena != NULL */
void *mark = NULL;
CK_RV crv;
PORT_Assert(slot->session != CK_INVALID_SESSION);
if (slot->session == CK_INVALID_SESSION)
return CKR_SESSION_HANDLE_INVALID;
@ -1506,6 +1505,7 @@ PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass)
/* initialize it */
obj->slot = PK11_ReferenceSlot(slot);
obj->objectID = objectIDs[i];
obj->owner = PR_FALSE;
obj->next = NULL;
obj->prev = NULL;
@ -1586,6 +1586,9 @@ PK11_DestroyGenericObject(PK11GenericObject *object)
PK11_UnlinkGenericObject(object);
if (object->slot) {
if (object->owner) {
PK11_DestroyObject(object->slot, object->objectID);
}
PK11_FreeSlot(object->slot);
}
PORT_Free(object);
@ -1627,8 +1630,9 @@ PK11_DestroyGenericObjects(PK11GenericObject *objects)
* Hand Create a new object and return the Generic object for our new object.
*/
PK11GenericObject *
PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
int count, PRBool token)
pk11_CreateGenericObjectHelper(PK11SlotInfo *slot,
const CK_ATTRIBUTE *pTemplate,
int count, PRBool token, PRBool owner)
{
CK_OBJECT_HANDLE objectID;
PK11GenericObject *obj;
@ -1652,11 +1656,40 @@ PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
/* initialize it */
obj->slot = PK11_ReferenceSlot(slot);
obj->objectID = objectID;
obj->owner = owner;
obj->next = NULL;
obj->prev = NULL;
return obj;
}
/* This is the classic interface. Applications would call this function to
* create new object that would not be destroyed later. This lead to resource
* leaks (and thus memory leaks in the PKCS #11 module). To solve this we have
* a new interface that automatically marks objects created on the fly to be
* destroyed later.
* The old interface is preserved because applications like Mozilla purposefully
* leak the reference to be found later with PK11_FindGenericObjects. New
* applications should use the new interface PK11_CreateManagedGenericObject */
PK11GenericObject *
PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
int count, PRBool token)
{
return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
PR_FALSE);
}
/* Use this interface. It will automatically destroy any temporary objects
* (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still
* need to be destroyed by hand with PK11_DestroyTokenObject.
*/
PK11GenericObject *
PK11_CreateManagedGenericObject(PK11SlotInfo *slot,
const CK_ATTRIBUTE *pTemplate, int count, PRBool token)
{
return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
!token);
}
/*
* Change an attribute on a raw object
*/

View file

@ -413,8 +413,7 @@ static const policyFlagDef policyFlagList[] = {
/* add other signatures in the future */
{ CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
/* enable everything */
{ CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX |
NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("NONE"), 0 }
};

View file

@ -367,7 +367,24 @@ sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId)
cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId);
if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlg)) {
length = sec_pkcs5v2_aes_key_length(cipherAlg);
/* Previously, the PKCS#12 files created with the old NSS
* releases encoded the maximum key size of AES (that is 32)
* in the keyLength field of PBKDF2-params. That resulted in
* always performing AES-256 even if AES-128-CBC or
* AES-192-CBC is specified in the encryptionScheme field of
* PBES2-params. This is wrong, but for compatibility reasons,
* check the keyLength field and use the value if it is 32.
*/
if (p5_param.keyLength.data != NULL) {
length = DER_GetInteger(&p5_param.keyLength);
}
/* If the keyLength field is present and contains a value
* other than 32, that means the file is created outside of
* NSS, which we don't care about. Note that the following
* also handles the case when the field is absent. */
if (length != 32) {
length = sec_pkcs5v2_aes_key_length(cipherAlg);
}
} else if (p5_param.keyLength.data != NULL) {
length = DER_GetInteger(&p5_param.keyLength);
} else {

View file

@ -153,7 +153,6 @@ const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.prime) },
};
#ifndef NSS_DISABLE_ECC
SEC_ASN1_MKSUB(SEC_BitStringTemplate)
SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
@ -178,7 +177,6 @@ const SEC_ASN1Template SECKEY_ECPrivateKeyExportTemplate[] = {
SEC_ASN1_SUB(SEC_BitStringTemplate) },
{ 0 }
};
#endif /* NSS_DISABLE_ECC */
const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
@ -346,16 +344,13 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
switch (lpk->keyType) {
case rsaKey:
keyType = CKK_RSA;
PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue
: &ckfalse,
PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue
: &ckfalse,
PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
: &ckfalse,
PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
@ -482,7 +477,6 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
lpk->u.dh.privateValue.len);
attrs++;
break;
#ifndef NSS_DISABLE_ECC
case ecKey:
keyType = CKK_EC;
if (lpk->u.ec.publicValue.len == 0) {
@ -494,8 +488,7 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
lpk->u.ec.publicValue.len);
attrs++;
}
PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
: &ckfalse,
PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
@ -503,8 +496,7 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
: &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue
: &ckfalse,
PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
ck_id = PK11_MakeIDFromPubKey(&lpk->u.ec.publicValue);
@ -525,7 +517,6 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
lpk->u.ec.publicValue.len);
attrs++;
break;
#endif /* NSS_DISABLE_ECC */
default:
PORT_SetError(SEC_ERROR_BAD_KEY);
goto loser;
@ -606,7 +597,6 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
paramDest = NULL;
lpk->keyType = dhKey;
break;
#ifndef NSS_DISABLE_ECC
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
prepare_ec_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
@ -614,7 +604,6 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
paramDest = NULL;
lpk->keyType = ecKey;
break;
#endif /* NSS_DISABLE_ECC */
default:
keyTemplate = NULL;
@ -633,7 +622,6 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
goto loser;
}
#ifndef NSS_DISABLE_ECC
if (lpk->keyType == ecKey) {
/* Convert length in bits to length in bytes. */
lpk->u.ec.publicValue.len >>= 3;
@ -645,7 +633,6 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
goto loser;
}
}
#endif /* NSS_DISABLE_ECC */
if (paramDest && paramTemplate) {
rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,

View file

@ -831,6 +831,10 @@ SECStatus PK11_LinkGenericObject(PK11GenericObject *list,
PK11GenericObject *object);
SECStatus PK11_DestroyGenericObjects(PK11GenericObject *object);
SECStatus PK11_DestroyGenericObject(PK11GenericObject *object);
PK11GenericObject *PK11_CreateManagedGenericObject(PK11SlotInfo *slot,
const CK_ATTRIBUTE *pTemplate,
int count, PRBool token);
/* deprecated */
PK11GenericObject *PK11_CreateGenericObject(PK11SlotInfo *slot,
const CK_ATTRIBUTE *pTemplate,
int count, PRBool token);

View file

@ -182,6 +182,10 @@ PK11_FreeSymKey(PK11SymKey *symKey)
PK11SlotInfo *slot;
PRBool freeit = PR_TRUE;
if (!symKey) {
return;
}
if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) {
PK11SymKey *parent = symKey->parent;

View file

@ -1182,7 +1182,7 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
/* set the slot flags to the current token values */
slot->series++; /* allow other objects to detect that the
* slot is different */
* slot is different */
slot->flags = slot->tokenInfo.flags;
slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE);
slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE);
@ -1471,6 +1471,9 @@ PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot)
slot->hasRootCerts = PR_TRUE;
}
}
if ((slotInfo.flags & CKF_USER_PIN_INITIALIZED) != 0) {
slot->flags |= CKF_USER_PIN_INITIALIZED;
}
}
/*********************************************************************

View file

@ -437,6 +437,11 @@ SECMOD_DeleteInternalModule(const char *name)
return rv;
}
#ifdef NSS_FIPS_DISABLED
PORT_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR);
return rv;
#endif
SECMOD_GetWriteLock(moduleLock);
for (mlpp = &modules, mlp = modules;
mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
@ -955,7 +960,11 @@ SECMOD_DestroyModuleList(SECMODModuleList *list)
PRBool
SECMOD_CanDeleteInternalModule(void)
{
#ifdef NSS_FIPS_DISABLED
return PR_FALSE;
#else
return (PRBool)(pendingModule == NULL);
#endif
}
/*

View file

@ -175,6 +175,7 @@ struct PK11GenericObjectStr {
PK11GenericObject *next;
PK11SlotInfo *slot;
CK_OBJECT_HANDLE objectID;
PRBool owner;
};
#define MAX_TEMPL_ATTRS 16 /* maximum attributes in template */

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nssrenam.h"
#include "nss.h"
#include "p12t.h"
#include "p12.h"
#include "plarena.h"
@ -126,6 +127,7 @@ struct SEC_PKCS12DecoderContextStr {
SECKEYGetPasswordKey pwfn;
void *pwfnarg;
PRBool swapUnicodeBytes;
PRBool forceUnicode;
/* import information */
PRBool bagsVerified;
@ -192,8 +194,18 @@ sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
}
algorithm = SECOID_GetAlgorithmTag(algid);
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem))
return NULL;
if (p12dcx->forceUnicode) {
if (SECITEM_CopyItem(NULL, &pwitem, p12dcx->pwitem) != SECSuccess) {
PK11_FreeSlot(slot);
return NULL;
}
} else {
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem)) {
PK11_FreeSlot(slot);
return NULL;
}
}
bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx);
/* some tokens can't generate PBE keys on their own, generate the
@ -1164,6 +1176,8 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
{
SEC_PKCS12DecoderContext *p12dcx;
PLArenaPool *arena;
PRInt32 forceUnicode = PR_FALSE;
SECStatus rv;
arena = PORT_NewArena(2048); /* different size? */
if (!arena) {
@ -1196,6 +1210,11 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
#else
p12dcx->swapUnicodeBytes = PR_FALSE;
#endif
rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
if (rv != SECSuccess) {
goto loser;
}
p12dcx->forceUnicode = forceUnicode;
p12dcx->errorValue = 0;
p12dcx->error = PR_FALSE;
@ -2428,7 +2447,7 @@ sec_pkcs12_get_public_value_and_type(SECKEYPublicKey *pubKey, KeyType *type);
static SECStatus
sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
unsigned int keyUsage,
SECItem *nickName, void *wincx)
SECItem *nickName, PRBool forceUnicode, void *wincx)
{
SECStatus rv;
SECItem *publicValue = NULL;
@ -2466,9 +2485,21 @@ sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
&key->safeBagContent.pkcs8ShroudedKeyBag->algorithm;
SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
key->pwitem))
return SECFailure;
if (forceUnicode) {
if (SECITEM_CopyItem(NULL, &pwitem, key->pwitem) != SECSuccess) {
key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
key->problem = PR_TRUE;
return SECFailure;
}
} else {
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
key->pwitem)) {
key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
key->problem = PR_TRUE;
return SECFailure;
}
}
rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot,
key->safeBagContent.pkcs8ShroudedKeyBag,
&pwitem, nickName, publicValue,
@ -2923,7 +2954,8 @@ sec_pkcs12_get_public_value_and_type(SECKEYPublicKey *pubKey,
* two passes in sec_pkcs12_validate_bags.
*/
static SECStatus
sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, PRBool forceUnicode,
void *wincx)
{
sec_PKCS12SafeBag **keyList;
int i;
@ -2976,7 +3008,8 @@ sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
key->problem = PR_TRUE;
rv = SECFailure;
} else {
rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName, wincx);
rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName,
forceUnicode, wincx);
}
if (pubKey) {
SECKEY_DestroyPublicKey(pubKey);
@ -3053,6 +3086,9 @@ sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
SECStatus
SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
{
PRBool forceUnicode = PR_FALSE;
SECStatus rv;
if (!p12dcx || p12dcx->error) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@ -3062,7 +3098,16 @@ SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
return SECFailure;
}
return sec_pkcs12_install_bags(p12dcx->safeBags, p12dcx->wincx);
/* We need to check the option here as well as in
* SEC_PKCS12DecoderStart, because different PBE's could be used
* for PKCS #7 and PKCS #8 */
rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
if (rv != SECSuccess) {
return SECFailure;
}
return sec_pkcs12_install_bags(p12dcx->safeBags, forceUnicode,
p12dcx->wincx);
}
PRBool

View file

@ -267,8 +267,7 @@ sec_pkcs12_generate_key_from_password(SECOidTag algorithm,
return NULL;
}
pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) *
(salt->len + password->len));
pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * (salt->len + password->len));
if (pre_hash == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;

View file

@ -18,7 +18,13 @@
#include "secder.h"
#include "secpkcs5.h"
const int NSS_PBE_DEFAULT_ITERATION_COUNT = 2000; /* used in p12e.c too */
const int NSS_PBE_DEFAULT_ITERATION_COUNT = /* used in p12e.c too */
#ifdef DEBUG
10000
#else
1000000
#endif
;
static SECStatus
sec_pkcs7_init_content_info(SEC_PKCS7ContentInfo *cinfo, PLArenaPool *poolp,

View file

@ -180,16 +180,18 @@ STAN_RemoveModuleFromDefaultTrustDomain(
NSSTrustDomain *td;
int i;
td = STAN_GetDefaultTrustDomain();
NSSRWLock_LockWrite(td->tokensLock);
for (i = 0; i < module->slotCount; i++) {
token = PK11Slot_GetNSSToken(module->slots[i]);
if (token) {
nssToken_NotifyCertsNotVisible(token);
NSSRWLock_LockWrite(td->tokensLock);
nssList_Remove(td->tokenList, token);
NSSRWLock_UnlockWrite(td->tokensLock);
PK11Slot_SetNSSToken(module->slots[i], NULL);
nssToken_Destroy(token);
}
}
NSSRWLock_LockWrite(td->tokensLock);
nssListIterator_Destroy(td->tokens);
td->tokens = nssList_CreateIterator(td->tokenList);
NSSRWLock_UnlockWrite(td->tokensLock);

View file

@ -87,8 +87,7 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth)
/* XXX error handling: need to set p7dcx->error */
#ifdef CMSDEBUG
fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before"
: "after",
fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before" : "after",
dest, depth);
#endif

View file

@ -134,8 +134,7 @@ nss_cms_encoder_notify(void *arg, PRBool before, void *dest, int depth)
rootcinfo = &(p7ecx->cmsg->contentInfo);
#ifdef CMSDEBUG
fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before"
: "after",
fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before" : "after",
dest, depth);
#endif

View file

@ -5,6 +5,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/. */
#ifndef NSS_FIPS_DISABLED
#include "seccomon.h"
#include "blapi.h"
#include "softoken.h"
@ -652,3 +653,11 @@ sftk_FIPSEntryOK()
}
return CKR_OK;
}
#else
#include "pkcs11t.h"
CK_RV
sftk_FIPSEntryOK()
{
return CKR_DEVICE_ERROR;
}
#endif /* NSS_FIPS_DISABLED */

View file

@ -540,7 +540,10 @@ FC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
crv = NSC_GetTokenInfo(slotID, pInfo);
if (crv == CKR_OK) {
if ((pInfo->flags & CKF_LOGIN_REQUIRED) == 0) {
/* use the global database to figure out if we are running in
* FIPS 140 Level 1 or Level 2 */
if (slotID == FIPS_SLOT_ID &&
(pInfo->flags & CKF_LOGIN_REQUIRED) == 0) {
isLevel2 = PR_FALSE;
}
}
@ -616,7 +619,8 @@ FC_InitPIN(CK_SESSION_HANDLE hSession,
* we need to make sure the pin meets FIPS requirements */
if ((ulPinLen == 0) || ((rv = sftk_newPinCheck(pPin, ulPinLen)) == CKR_OK)) {
rv = NSC_InitPIN(hSession, pPin, ulPinLen);
if (rv == CKR_OK) {
if ((rv == CKR_OK) &&
(sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID)) {
isLevel2 = (ulPinLen > 0) ? PR_TRUE : PR_FALSE;
}
}
@ -644,7 +648,8 @@ FC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
if ((rv = sftk_fipsCheck()) == CKR_OK &&
(rv = sftk_newPinCheck(pNewPin, usNewLen)) == CKR_OK) {
rv = NSC_SetPIN(hSession, pOldPin, usOldLen, pNewPin, usNewLen);
if (rv == CKR_OK) {
if ((rv == CKR_OK) &&
(sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID)) {
/* if we set the password in level1 we now go
* to level2. NOTE: we don't allow the user to
* go from level2 to level1 */
@ -705,11 +710,23 @@ FC_GetSessionInfo(CK_SESSION_HANDLE hSession,
rv = NSC_GetSessionInfo(hSession, pInfo);
if (rv == CKR_OK) {
if ((isLoggedIn) && (pInfo->state == CKS_RO_PUBLIC_SESSION)) {
pInfo->state = CKS_RO_USER_FUNCTIONS;
}
if ((isLoggedIn) && (pInfo->state == CKS_RW_PUBLIC_SESSION)) {
pInfo->state = CKS_RW_USER_FUNCTIONS;
/* handle the case where the auxilary slot doesn't require login.
* piggy back on the main token's login state */
if (isLoggedIn &&
((pInfo->state == CKS_RO_PUBLIC_SESSION) ||
(pInfo->state == CKS_RW_PUBLIC_SESSION))) {
CK_RV crv;
CK_TOKEN_INFO tInfo;
crv = NSC_GetTokenInfo(sftk_SlotIDFromSessionHandle(hSession),
&tInfo);
/* if the token doesn't login, use our global login state */
if ((crv == CKR_OK) && ((tInfo.flags & CKF_LOGIN_REQUIRED) == 0)) {
if (pInfo->state == CKS_RO_PUBLIC_SESSION) {
pInfo->state = CKS_RO_USER_FUNCTIONS;
} else {
pInfo->state = CKS_RW_USER_FUNCTIONS;
}
}
}
}
return rv;

View file

@ -1137,12 +1137,10 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer
namekey.data = pubkey->u.dh.publicValue.data;
namekey.size = pubkey->u.dh.publicValue.len;
break;
#ifndef NSS_DISABLE_ECC
case NSSLOWKEYECKey:
namekey.data = pubkey->u.ec.publicValue.data;
namekey.size = pubkey->u.ec.publicValue.len;
break;
#endif /* NSS_DISABLE_ECC */
default:
/* XXX We don't do Fortezza or DH yet. */
return PR_FALSE;
@ -1467,12 +1465,10 @@ seckey_encrypt_private_key(PLArenaPool *permarena, NSSLOWKEYPrivateKey *pk,
SECItem *der_item = NULL;
SECItem *cipherText = NULL;
SECItem *dummy = NULL;
#ifndef NSS_DISABLE_ECC
#ifdef EC_DEBUG
SECItem *fordebug = NULL;
#endif
int savelen;
#endif
temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (temparena == NULL)
@ -1548,7 +1544,6 @@ seckey_encrypt_private_key(PLArenaPool *permarena, NSSLOWKEYPrivateKey *pk,
goto loser;
}
break;
#ifndef NSS_DISABLE_ECC
case NSSLOWKEYECKey:
lg_prepare_low_ec_priv_key_for_asn1(pk);
/* Public value is encoded as a bit string so adjust length
@ -1589,7 +1584,6 @@ seckey_encrypt_private_key(PLArenaPool *permarena, NSSLOWKEYPrivateKey *pk,
#endif
break;
#endif /* NSS_DISABLE_ECC */
default:
/* We don't support DH or Fortezza private keys yet */
PORT_Assert(PR_FALSE);
@ -1809,7 +1803,6 @@ seckey_decrypt_private_key(SECItem *epki,
lg_nsslowkey_DHPrivateKeyTemplate,
&newPrivateKey);
break;
#ifndef NSS_DISABLE_ECC
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
pk->keyType = NSSLOWKEYECKey;
lg_prepare_low_ec_priv_key_for_asn1(pk);
@ -1849,7 +1842,6 @@ seckey_decrypt_private_key(SECItem *epki,
}
break;
#endif /* NSS_DISABLE_ECC */
default:
rv = SECFailure;
break;

View file

@ -133,7 +133,7 @@ lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type,
attr->ulValueLen = (CK_ULONG)-1;
return CKR_BUFFER_TOO_SMALL;
}
if (value != NULL) {
if (len > 0 && value != NULL) {
PORT_Memcpy(attr->pValue, value, len);
}
attr->ulValueLen = len;
@ -421,11 +421,9 @@ lg_GetPubItem(NSSLOWKEYPublicKey *pubKey)
case NSSLOWKEYDHKey:
pubItem = &pubKey->u.dh.publicValue;
break;
#ifndef NSS_DISABLE_ECC
case NSSLOWKEYECKey:
pubItem = &pubKey->u.ec.publicValue;
break;
#endif /* NSS_DISABLE_ECC */
default:
break;
}
@ -544,7 +542,6 @@ lg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
return lg_invalidAttribute(attribute);
}
#ifndef NSS_DISABLE_ECC
static CK_RV
lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
CK_ATTRIBUTE *attribute)
@ -594,7 +591,6 @@ lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
}
return lg_invalidAttribute(attribute);
}
#endif /* NSS_DISABLE_ECC */
static CK_RV
lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
@ -645,10 +641,8 @@ lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
return lg_FindDSAPublicKeyAttribute(key, type, attribute);
case NSSLOWKEYDHKey:
return lg_FindDHPublicKeyAttribute(key, type, attribute);
#ifndef NSS_DISABLE_ECC
case NSSLOWKEYECKey:
return lg_FindECPublicKeyAttribute(key, type, attribute);
#endif /* NSS_DISABLE_ECC */
default:
break;
}
@ -935,7 +929,6 @@ lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
return lg_invalidAttribute(attribute);
}
#ifndef NSS_DISABLE_ECC
static CK_RV
lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
CK_ATTRIBUTE *attribute, SDB *sdbpw)
@ -973,7 +966,6 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
}
return lg_invalidAttribute(attribute);
}
#endif /* NSS_DISABLE_ECC */
static CK_RV
lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
@ -1020,10 +1012,8 @@ lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
return lg_FindDSAPrivateKeyAttribute(key, type, attribute, obj->sdb);
case NSSLOWKEYDHKey:
return lg_FindDHPrivateKeyAttribute(key, type, attribute, obj->sdb);
#ifndef NSS_DISABLE_ECC
case NSSLOWKEYECKey:
return lg_FindECPrivateKeyAttribute(key, type, attribute, obj->sdb);
#endif /* NSS_DISABLE_ECC */
default:
break;
}

View file

@ -398,21 +398,17 @@ lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
NSSLOWKEYPrivateKey *priv;
SECItem pubKeySpace = { siBuffer, NULL, 0 };
SECItem *pubKey;
#ifndef NSS_DISABLE_ECC
SECItem pubKey2Space = { siBuffer, NULL, 0 };
PLArenaPool *arena = NULL;
#endif /* NSS_DISABLE_ECC */
NSSLOWKEYDBHandle *keyHandle = NULL;
switch (key_type) {
case CKK_RSA:
pubKeyAttr = CKA_MODULUS;
break;
#ifndef NSS_DISABLE_ECC
case CKK_EC:
pubKeyAttr = CKA_EC_POINT;
break;
#endif /* NSS_DISABLE_ECC */
case CKK_DSA:
case CKK_DH:
break;
@ -425,7 +421,6 @@ lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
if (crv != CKR_OK)
return crv;
#ifndef NSS_DISABLE_ECC
if (key_type == CKK_EC) {
SECStatus rv;
/*
@ -448,7 +443,6 @@ lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
pubKey = &pubKey2Space;
}
}
#endif /* NSS_DISABLE_ECC */
PORT_Assert(pubKey->data);
if (pubKey->data == NULL) {
@ -469,14 +463,12 @@ lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
/* make sure the associated private key already exists */
/* only works if we are logged in */
priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, sdb /*password*/);
#ifndef NSS_DISABLE_ECC
if (priv == NULL && pubKey == &pubKey2Space) {
/* no match on the decoded key, match the original pubkey */
pubKey = &pubKeySpace;
priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey,
sdb /*password*/);
}
#endif
if (priv == NULL) {
/* the legacy database can only 'store' public keys which already
* have their corresponding private keys in the database */
@ -490,10 +482,9 @@ lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
done:
PORT_Free(pubKeySpace.data);
#ifndef NSS_DISABLE_ECC
if (arena)
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
#endif
}
return crv;
}
@ -613,7 +604,6 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
}
break;
#ifndef NSS_DISABLE_ECC
case CKK_EC:
privKey->keyType = NSSLOWKEYECKey;
crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS, templ, count,
@ -646,7 +636,6 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
if (rv != SECSuccess)
crv = CKR_HOST_MEMORY;
break;
#endif /* NSS_DISABLE_ECC */
default:
crv = CKR_KEY_TYPE_INCONSISTENT;

View file

@ -6,6 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: fipstest.c,v 1.31 2012/06/28 17:55:06 rrelyea%redhat.com Exp $ */
#ifndef NSS_FIPS_DISABLED
#include "seccomon.h"
#include "lgdb.h"
#include "blapi.h"
@ -113,3 +115,5 @@ lg_FIPSEntryOK()
#endif
return lg_self_tests_success;
}
#endif /* NSS_FIPS_DISABLED */

View file

@ -586,11 +586,15 @@ legacy_Open(const char *configdir, const char *certPrefix,
#define NSS_VERSION_VARIABLE __nss_dbm_version
#include "verref.h"
#ifndef NSS_FIPS_DISABLED
if (flags & SDB_FIPS) {
/* We shouldn't get here when FIPS is not enabled on the database. But
* we also don't care when this NSS build doesn't support FIPS. */
if (!lg_FIPSEntryOK()) {
return CKR_DEVICE_ERROR;
}
}
#endif
rv = SECOID_Init();
if (SECSuccess != rv) {

View file

@ -823,7 +823,6 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
if (rv == SECSuccess)
return pubk;
break;
#ifndef NSS_DISABLE_ECC
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
pubk->keyType = NSSLOWKEYECKey;
/* Since PKCS#11 directly takes the DER encoding of EC params
@ -845,7 +844,6 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
if (rv == SECSuccess)
return pubk;
break;
#endif /* NSS_DISABLE_ECC */
default:
rv = SECFailure;
break;

View file

@ -99,8 +99,6 @@ const SEC_ASN1Template lg_nsslowkey_DHPrivateKeyTemplate[] = {
{ 0 }
};
#ifndef NSS_DISABLE_ECC
/* NOTE: The SECG specification allows the private key structure
* to contain curve parameters but recommends that they be stored
* in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
@ -193,7 +191,6 @@ LGEC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
loser:
return SECFailure;
}
#endif /* NSS_DISABLE_ECC */
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
@ -243,7 +240,6 @@ lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
key->u.dh.privateValue.type = siUnsignedInteger;
}
#ifndef NSS_DISABLE_ECC
void
lg_prepare_low_ecparams_for_asn1(ECParams *params)
{
@ -260,7 +256,6 @@ lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
key->u.ec.privateValue.type = siUnsignedInteger;
key->u.ec.publicValue.type = siUnsignedInteger;
}
#endif /* NSS_DISABLE_ECC */
void
lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
@ -362,7 +357,6 @@ lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
return pubk;
}
break;
#ifndef NSS_DISABLE_ECC
case NSSLOWKEYECKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
@ -383,7 +377,6 @@ lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
return pubk;
}
break;
#endif /* NSS_DISABLE_ECC */
/* No Fortezza in Low Key implementations (Fortezza keys aren't
* stored in our data base */
default:

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