зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1705477 - land NSS 1d066793c349 UPGRADE_NSS_RELEASE, r=beurdouche
2021-05-06 Martin Thomson <mt@lowentropy.net> * gtests/pk11_gtest/pk11_hpke_unittest.cc: Bug 1709750 - Disable HPKE test when fuzzing, r=bbeurdouche [1d066793c349] [tip] 2021-05-05 Benjamin Beurdouche <bbeurdouche@mozilla.com> * lib/freebl/ppc-gcm-wrap.c, lib/freebl/ppc-gcm.h: Bug 1566124 - Clang format run. r=beurdouche [cb714d62058c] 2021-05-05 mamonet <maamoun.tk@gmail.com> * lib/freebl/Makefile, lib/freebl/freebl.gyp, lib/freebl/ppc-gcm- wrap.c, lib/freebl/ppc-gcm.h, lib/freebl/ppc-gcm.s, lib/freebl/rijndael.c: [1133fef2f7ce] 2021-03-17 Martin Thomson <mt@lowentropy.net> * gtests/common/testvectors/hpke-convert.py, gtests/common/testvectors/hpke-vectors.h, lib/pk11wrap/pk11hpke.c, lib/pk11wrap/pk11hpke.h: Bug 1699021 - Add AES-256-GCM to HPKE, r=bbeurdouche [9fa53d717386] * automation/abi-check/expected-report-libssl3.so.txt, cmd/selfserv/selfserv.c, gtests/ssl_gtest/libssl_internals.c, gtests/ssl_gtest/libssl_internals.h, gtests/ssl_gtest/tls_connect.cc, gtests/ssl_gtest/tls_connect.h, gtests/ssl_gtest/tls_ech_unittest.cc, lib/ssl/sslexp.h, lib/ssl/sslsock.c, lib/ssl/sslt.h, lib/ssl/tls13ech.c, lib/ssl/tls13ech.h, lib/ssl/tls13exthandle.c, lib/ssl/tls13hashstate.c, lib/ssl/tls13hashstate.h: Bug 1698419 - ECH -10 updates, r=bbeurdouche The main changes here are: * an update to HPKE -08 * a move to the single-byte configuration ID * reordering of ECHConfig The addition of the explicit configuration ID means that the API for constructing ECHConfig(List) needs to change. That means a name change, unfortunately. I took the opportunity to make further changes to the arguments. [fa93bd88b690] 2021-03-16 Martin Thomson <mt@lowentropy.net> * coreconf/config.gypi, coreconf/config.mk, gtests/common/testvectors/hpke-convert.py, gtests/common/testvectors/hpke-vectors.h, gtests/pk11_gtest/pk11_hpke_unittest.cc, gtests/ssl_gtest/ssl_auth_unittest.cc, gtests/ssl_gtest/ssl_tls13compat_unittest.cc, gtests/ssl_gtest/tls_ech_unittest.cc, lib/pk11wrap/pk11hpke.c, lib/pk11wrap/pk11hpke.h, lib/pk11wrap/pk11pub.h, lib/ssl/tls13ech.c: Bug 1692930 - Update HPKE to final version, r=bbeurdouche This adds the final HPKE version string. This removes the draft version markers from the implementation and stops tracking the draft version with the exported syntax. I've added the script that I used to convert the JSON test vectors from the specification; that should allow us to pick up new tests relatively easily, especially if we need to add new algorithms. This change breaks several ECH test cases. As fixing those tests is extraordinarily fiddly, I'm going to defer making those changes until we need to update ECH. As we can't land this code until ECH is updated to depend on the final HPKE and until we have coordinated with servers on when the ECH update can be deployed, it should be OK to defer. In short, don't land this without the matching ECH changes. [e78141a928f4] 2021-05-04 Robert Relyea <rrelyea@redhat.com> * automation/abi-check/expected-report-libnss3.so.txt, cmd/lib/basicutil.h, cmd/lib/secutil.c, cmd/lib/secutil.h, cmd/pk12util/pk12util.c, cmd/pp/pp.c, doc/pk12util.xml, doc/pp.xml, lib/nss/nss.def, lib/pk11wrap/pk11akey.c, lib/pk11wrap/pk11pub.h, lib/pkcs12/p12d.c, lib/pkcs12/p12e.c, lib/pkcs12/p12local.c, lib/pkcs12/p12local.h, lib/pkcs12/p12plcy.c, lib/util/secoidt.h, tests/tools/tools.sh: Bug 1707130 NSS should use modern algorithms in PKCS#12 files by default r=mt Also fixes: Bug 452464 pk12util -o fails when -C option specifies AES or Camellia ciphers Related: Bug 1694689 Firefox should use modern algorithms in PKCS#12 files by default Bug 452471 pk12util -o fails when -c option specifies pkcs12v2 PBE ciphers The base of this fix is was a simple 3 line fix in pkcs12.c, changing the initial setting of cipher and cert cipher. Overview for why this patch is larger than just 3 lines: 1. First issue was found in trying to change the mac hashing value. a. While the decrypt side knew how to handle SHA2 hashes, the equivalent code was not updated on the encrypt side. I refactored that code and placed the common function in p12local.c. Now p12e.c and p12d.c share common code to find the required function to produce the mac key. b. The prf hmac was hard coded to SHA1. I changed the code to pass the hmac matching the hashing algorithm for the mac. This required changes to p12e.c to calculate and pass the new hmac as well and adding new PK11_ExportEncryptedPrivateKey and PK11_ExportEncryptedPrivKey to take the PKCS #5 v2 parameters. I also corrected an error which prevented pkcs12 encoding of ciphers other than AES. 2. Once I've made my changes, I realized we didn't have a way of testing them. While we had code that verified that particular sets of parameters for pkcs12 worked together and could be listed and imported, we didn't have a way to verify what algorithms were actually generated by our tools. a. pk12util -l doesn't list the encryption used for the certs, so I updated pp to take a pkcs12 option. In doing so I had to update pp to handle indefinite encoding when decoding blocks. I also factored that decoding out in it's own function so the change only needed to be placed once. Finally I renabled a function which prints the output of an EncryptedPrivate key. This function was disabled long ago when the Encrypted Private key info was made private for NSS. It has since been exported, so these functions could easily be enabled (archeological note: I verified that this disabling was not a recent think I found I had done it back when I still have a netscape email address;). b. I updated tools.sh to us the new pp -t pkcs12 feature to verify that the key encryption, cert encryption, and hash functions matched what we expected when we exported a new key. I also updated tools.sh to handle the new hash variable option to pk12util. c. I discovered several tests commented out with comments that the don't work. I enabled those tests and discovered that they can now encrypt, but the can't decrypt because of pkcs12 policy. I updated the policy code, but I updated it to use the new NSS system wide policy mechanism. This enabled all the ciphers to work. There is still policy work to do. The pk12 policy currently only prevents ciphers from use in decrypting the certificates, not decrypting the keys and not encrypting. I left that for future work. 3. New options for pp and pk12util were added to the man pages for these tools. -------------------------------------------------------------------- ------- With that in mind, here's a file by file description of the patch: automation/abi-check/expected-report-libnss3.so.txt -Add new exported functions. (see lib/nss/nss.def) cmd/lib/basicutil.h: -Removed the HAVE_EPV_TEMPLATE ifdefs (NSS has exported the Encrypted Private Key data structure for a while now. cmd/lib/secutil.c: global: Updated several functions to take a const char * m (message) rather than a char * m global: Made the various PrintPKCS7 return an error code. global: Added a state variable to be passed around the various PKCS7 Print functions. It gives the proper context to interpret PKCS7 Data Content. PKCS 12 used PKCS7 to package the various PKCS12 Safes and Bags. -Updated SECU_StripTagAndLength to handle indefinite encoding, and to set the Error code. -Added SECU_ExtractDERAndStep to grab the next DER Tag, Length, and Data. -Updated secu_PrintRawStringQuotesOptional to remove the inline DER parsing and use SECU_ExtractDERAndStep(). -Updated SECU_PrintEncodedObjectID to return the SECOidTag just like SECU_PrintObjectID. -Renable SECU_PrintPrivateKey -Added secu_PrintPKCS12Attributes to print out the Attributes tied to a PKCS #12 Bag -Added secu_PrintPKCS12Bag to print out a PKCS #12 Bag -Added secu_PrintPKCS7Data, which uses the state to determine what it was printing out. -Added secu_PrintDERPKCS7ContentInfo which is identical to the global function SECU_PrintPKCS7ContentInfo except it takes a state variable. The latter function now calls the former. -Added secu_PrintPKCS12DigestInfo to print the Hash information of the Mac. DigestInfo is the name in the PKCS 12 spec. -Added secu_PrintPKCS12MacData to print the Mac portion of the PKCS 12 file. -Added SECU_PrintPKCS12 to print otu the pkcs12 file. cmd/lib/secutil.h -Added string for pkc12 for the command line of pp reenabled SECU_PrintPrivateKey -Added SECU_PrintPKCS12 for export. cmd/pk12util/pk12util.c -Added the -M option to specify a hash algorithm for the mac. updated P12U_ExportPKCS12Object: pass the hash algorithm to the PasswordIntegrity handler. -Added PKCS12U_FindTagFromString: generalized string to SECOidTag which only filters based on the oid having a matching PKCS #11 mechanism. updated PKCS12U_MapCipherFromString to call use PKCS12U_FindTagFromString to get the candidate tag before doing it's post processing to decide if the tag is really an encryption algorithm. -Added PKCS12U_MapHashFromString with is like MapCipherFromString except it verifies the resulting tag is a hash object. -Updated main to 1) change the default cipher, change the default certCipher, and process the new hash argument. NOTE: in the old code we did not encrypt the certs in FIPS mode. That's because the certs were encrypted with RC4 in the default pkcs12 file, which wasn't a FIPS algorithm. Since AES is, we can use it independent on whether or not we are in FIPS mode. cmd/pp/pp.c -Added the pkcs12 option which calls SECU_PrintPKCS12 from secutil.c lib/nss/nss.def -Add exports to the new PK11_ExportEncryptedPrivKeyInfoV2 and PK11_ExportEncryptedPrivateKeyInfoV2 (V2 means PKCS 5 v2, not Version 2 of ExportEncrypted*Info). -Add export for the old HASH_GetHMACOidTagByHashOidTag which should have been exported long ago to avoid the proliferation of copies of this function in places like ssl. lib/pk11wrap/pk11akey.c -Add PK11_ExportEncryptedPrivKeyInfoV2 (which the old function now calls), which takes the 3 PKCS 5 v2 parameters. The underlying pkcs5 code can fill in missing tags if necessary, but supplying all three gives the caller full control of the underlying pkcs5 PBE used. -Add PK11_ExportEncryptedPrivateKeyInfoV2, same as the above function except it takes a cert which is used to look up the private key. It's the function that pkcs12 actually uses, but the former was exported for completeness. lib/pk11wrap/pk11pub.h -Added the new PK11_ExportEncryptedPriv*KeyInfoV2 functions. lib/pkcs12/p12d.c -Remove the switch statement and place it in p12local.c so that p12e.c can use the same function. lib/pkc12/p12e.c -Remove the unnecessary privAlg check so we can encode any mechanism we support. This only prevented encoding certificates in the pk12 file, not the keys. -add code to get the hmac used in the pbe prf from the integrity hash, which is under application control. -Do the same for key encryption, then use the new PK11_ExportEncryptedPrivateKeyInfo to pass that hash value. -Use the new sec_pkcs12_algtag_to_keygen_mech so there is only one switch statement to update rather than 2. -Update the hash data to old the length of the largest hash rather than the length of a SHA1 hash. lib/pkcs12/p12local.c - Add new function new sec_pkcs12_algtag_to_keygen_mech to factor out the common switch statement between p12e and p12d. lib/pkcs12/p12local.h -Export the new sec_pkcs12_algtag_to_keygen_mech lib/pkcs12/p12plcy.c -Map the old p12 policy functions to use the new NSS_GetAlgorithmPolicy. We keep the old table so that applications can change the policy with the old PKCS12 specific defines (so the old code keeps working). NOTE: policies now default to true rather than false. lib/util/secoidt.h -Add new NSS_USE_ALG_IN_PKCS12 used by pk11plcy.c NOTE: I have not updated the policy table in pk11wrap/pk11pars.c, so we can't yet control pkcs12 policy with the nss system policy table. That's a patch for another time. test/tools/tool.sh -global: Remove trailing spaces -global: DEFAULT is changed to 'default' -Update the PBE mechanism to exactly match the string in secoid.c. PKCS #12 does case independent compares, so case doesn't matter there, but now I'm comparing to the output of pp, and I didn't want to spend the time to figure out case independent compares in bash. -Add our defauts and shell variables at the top so there are easy to change in the future. export_with_*** have all been colapsed into a single export_p12_file which handles taking 'default' and turning off that argument. -Add for loops for the hash functions. -Restore the camellia ciphers back now that they work. -Restore the pkcs12V2pbe back now that they work. -Collect various pbe types into single variables and use those variables in loops -Reduce the number of tests ran in optimized mode (which takes 60x the time to do a pbe then than debug mode based on a larger iterator). -Add verify_p12 which dumps out the p12 file and makes sure the expected CERT_ENCRYPTION, KEY_ENCRYPTION, and HASH are used. doc/pp.xml -Add pkcs12 option doc/pk12util.xml -Add -M option -Update synopsis with options in the description but not in the synopsis [0a1687e1b39e] Differential Revision: https://phabricator.services.mozilla.com/D114584
This commit is contained in:
Родитель
d7b0e6c762
Коммит
6f107407c9
|
@ -1 +1 @@
|
|||
c982fb957516
|
||||
1d066793c349
|
|
@ -1,8 +1,11 @@
|
|||
|
||||
2 Added functions:
|
||||
5 Added functions:
|
||||
|
||||
'function SECOidTag HASH_GetHMACOidTagByHashOidTag(SECOidTag)' {HASH_GetHMACOidTagByHashOidTag@@NSS_3.65}
|
||||
'function PK11Context* PK11_CreateContextByPrivKey(CK_MECHANISM_TYPE, CK_ATTRIBUTE_TYPE, SECKEYPrivateKey*, const SECItem*)' {PK11_CreateContextByPrivKey@@NSS_3.65}
|
||||
'function PK11Context* PK11_CreateContextByPubKey(CK_MECHANISM_TYPE, CK_ATTRIBUTE_TYPE, SECKEYPublicKey*, const SECItem*, void*)' {PK11_CreateContextByPubKey@@NSS_3.65}
|
||||
'function SECKEYEncryptedPrivateKeyInfo* PK11_ExportEncryptedPrivKeyInfoV2(PK11SlotInfo*, SECOidTag, SECOidTag, SECOidTag, SECItem*, SECKEYPrivateKey*, int, void*)' {PK11_ExportEncryptedPrivKeyInfoV2@@NSS_3.65}
|
||||
'function SECKEYEncryptedPrivateKeyInfo* PK11_ExportEncryptedPrivateKeyInfoV2(PK11SlotInfo*, SECOidTag, SECOidTag, SECOidTag, SECItem*, CERTCertificate*, int, void*)' {PK11_ExportEncryptedPrivateKeyInfoV2@@NSS_3.65}
|
||||
|
||||
1 function with some indirect sub-type change:
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
1 function with some indirect sub-type change:
|
||||
|
||||
[C]'function SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc*, SSLExtensionType, PRBool*)' at sslreveal.c:72:1 has some indirect sub-type changes:
|
||||
parameter 2 of type 'typedef SSLExtensionType' has sub-type changes:
|
||||
underlying type 'enum __anonymous_enum__' at sslt.h:519:1 changed:
|
||||
type size hasn't changed
|
||||
1 enumerator change:
|
||||
'__anonymous_enum__::ssl_tls13_encrypted_client_hello_xtn' from value '65033' to '65034' at sslt.h:519:1
|
||||
|
||||
|
|
@ -54,10 +54,8 @@ extern void SECU_PrintAsHex(FILE *out, const SECItem *i, const char *m,
|
|||
/* dump a buffer in hex and ASCII */
|
||||
extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len);
|
||||
|
||||
#ifdef HAVE_EPV_TEMPLATE
|
||||
/* Dump contents of private key */
|
||||
extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
|
||||
#endif
|
||||
|
||||
/* Init PKCS11 stuff */
|
||||
extern SECStatus SECU_PKCS11Init(PRBool readOnly);
|
||||
|
|
|
@ -562,20 +562,110 @@ SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
|
|||
|
||||
#define INDENT_MULT 4
|
||||
|
||||
/*
|
||||
* remove the tag and length and just leave the bare BER data
|
||||
*/
|
||||
SECStatus
|
||||
SECU_StripTagAndLength(SECItem *i)
|
||||
{
|
||||
unsigned int start;
|
||||
PRBool isIndefinite;
|
||||
|
||||
if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
isIndefinite = (i->data[1] == 0x80);
|
||||
start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
|
||||
if (i->len < start) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
i->data += start;
|
||||
i->len -= start;
|
||||
/* we are using indefinite encoding, drop the trailing zero */
|
||||
if (isIndefinite) {
|
||||
if (i->len <= 1) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
/* verify tags are zero */
|
||||
if ((i->data[i->len - 1] != 0) || (i->data[i->len - 2] != 0)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
i->len -= 2;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new SECItem which points to the current BER tag and length with
|
||||
* all it's data. For indefinite encoding, this will also include the trailing
|
||||
* indefinite markers
|
||||
* The 'in' item is advanced to point to the next BER tag.
|
||||
* You don't want to use this in an actual BER/DER parser as NSS already
|
||||
* has 3 to choose from)
|
||||
*/
|
||||
SECStatus
|
||||
SECU_ExtractBERAndStep(SECItem *in, SECItem *out)
|
||||
{
|
||||
if (!in || !in->data || in->len < 2) { /* must be at least tag and length */
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
*out = *in;
|
||||
|
||||
/* first handle indefinite encoding */
|
||||
if (out->data[1] == 0x80) {
|
||||
SECItem this = *out;
|
||||
SECItem next;
|
||||
this.data += 2;
|
||||
this.len -= 2;
|
||||
out->len = 2;
|
||||
/* walk through all the entries until we find the '0' */
|
||||
while ((this.len >= 2) && (this.data[0] != 0)) {
|
||||
SECStatus rv = SECU_ExtractBERAndStep(&this, &next);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
out->len += next.len;
|
||||
}
|
||||
if ((this.len < 2) || ((this.data[0] != 0) && (this.data[1] != 0))) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
out->len += 2; /* include the trailing zeros */
|
||||
in->data += out->len;
|
||||
in->len -= out->len;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* now handle normal DER encoding */
|
||||
if (out->data[1] & 0x80) {
|
||||
unsigned int i;
|
||||
unsigned int lenlen = out->data[1] & 0x7f;
|
||||
unsigned int len = 0;
|
||||
if (lenlen > sizeof out->len) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
for (i = 0; i < lenlen; i++) {
|
||||
len = (len << 8) | out->data[2 + i];
|
||||
}
|
||||
out->len = len + lenlen + 2;
|
||||
} else {
|
||||
out->len = out->data[1] + 2;
|
||||
}
|
||||
if (out->len > in->len) {
|
||||
/* we've ran into a truncated file */
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
in->data += out->len;
|
||||
in->len -= out->len;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
@ -786,26 +876,10 @@ SECU_PrintSet(FILE *out, const SECItem *t, const char *m, int level)
|
|||
fprintf(out, "%s{\n", label); /* } */
|
||||
|
||||
while (my.len >= 2) {
|
||||
SECItem tmp = my;
|
||||
|
||||
if (tmp.data[1] & 0x80) {
|
||||
unsigned int i;
|
||||
unsigned int lenlen = tmp.data[1] & 0x7f;
|
||||
if (lenlen > sizeof tmp.len)
|
||||
break;
|
||||
tmp.len = 0;
|
||||
for (i = 0; i < lenlen; i++) {
|
||||
tmp.len = (tmp.len << 8) | tmp.data[2 + i];
|
||||
}
|
||||
tmp.len += lenlen + 2;
|
||||
} else {
|
||||
tmp.len = tmp.data[1] + 2;
|
||||
SECItem tmp;
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &tmp)) {
|
||||
break;
|
||||
}
|
||||
if (tmp.len > my.len) {
|
||||
tmp.len = my.len;
|
||||
}
|
||||
my.data += tmp.len;
|
||||
my.len -= tmp.len;
|
||||
SECU_PrintAny(out, &tmp, NULL, level + 1);
|
||||
}
|
||||
SECU_Indent(out, level);
|
||||
|
@ -906,12 +980,14 @@ SECU_PrintEncodedInteger(FILE *out, const SECItem *i, const char *m, int level)
|
|||
}
|
||||
|
||||
/* Print a DER encoded OID */
|
||||
void
|
||||
SECOidTag
|
||||
SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
|
||||
{
|
||||
SECItem my = *i;
|
||||
SECOidTag tag = SEC_OID_UNKNOWN;
|
||||
if (SECSuccess == SECU_StripTagAndLength(&my))
|
||||
SECU_PrintObjectID(out, &my, m, level);
|
||||
tag = SECU_PrintObjectID(out, &my, m, level);
|
||||
return tag;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2455,7 +2531,6 @@ SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
|
|||
return rv;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EPV_TEMPLATE
|
||||
int
|
||||
SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
|
||||
{
|
||||
|
@ -2482,7 +2557,6 @@ loser:
|
|||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
|
||||
|
@ -2545,16 +2619,26 @@ SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
|
|||
*/
|
||||
|
||||
/* forward declaration */
|
||||
typedef enum {
|
||||
secuPKCS7Unknown = 0,
|
||||
secuPKCS7PKCS12AuthSafe,
|
||||
secuPKCS7PKCS12Safe
|
||||
} secuPKCS7State;
|
||||
|
||||
static int
|
||||
secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
|
||||
secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, secuPKCS7State,
|
||||
const char *, int);
|
||||
static int
|
||||
secu_PrintDERPKCS7ContentInfo(FILE *, SECItem *, secuPKCS7State,
|
||||
const char *, int);
|
||||
|
||||
/*
|
||||
** secu_PrintPKCS7EncContent
|
||||
** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
|
||||
char *m, int level)
|
||||
secuPKCS7State state, const char *m, int level)
|
||||
{
|
||||
if (src->contentTypeTag == NULL)
|
||||
src->contentTypeTag = SECOID_FindOID(&(src->contentType));
|
||||
|
@ -2569,6 +2653,7 @@ secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
|
|||
"Content Encryption Algorithm", level + 1);
|
||||
SECU_PrintAsHex(out, &(src->encContent),
|
||||
"Encrypted Content", level + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2576,8 +2661,8 @@ secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
|
|||
** Prints a PKCS7RecipientInfo type
|
||||
*/
|
||||
static void
|
||||
secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
|
||||
int level)
|
||||
secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info,
|
||||
const char *m, int level)
|
||||
{
|
||||
SECU_Indent(out, level);
|
||||
fprintf(out, "%s:\n", m);
|
||||
|
@ -2599,7 +2684,8 @@ secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
|
|||
** Prints a PKCS7SingerInfo type
|
||||
*/
|
||||
static void
|
||||
secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
|
||||
secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info,
|
||||
const char *m, int level)
|
||||
{
|
||||
SEC_PKCS7Attribute *attr;
|
||||
int iv;
|
||||
|
@ -2691,7 +2777,7 @@ SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
|
|||
*/
|
||||
static int
|
||||
secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
|
||||
const char *m, int level)
|
||||
secuPKCS7State state, const char *m, int level)
|
||||
{
|
||||
SECAlgorithmID *digAlg; /* digest algorithms */
|
||||
SECItem *aCert; /* certificate */
|
||||
|
@ -2717,7 +2803,7 @@ secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
|
|||
|
||||
/* Now for the content */
|
||||
rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
|
||||
"Content Information", level + 1);
|
||||
state, "Content Information", level + 1);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
|
@ -2772,9 +2858,9 @@ secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
|
|||
** secu_PrintPKCS7Enveloped
|
||||
** Pretty print a PKCS7 enveloped data type (up to version 1).
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
|
||||
const char *m, int level)
|
||||
secuPKCS7State state, const char *m, int level)
|
||||
{
|
||||
SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
|
||||
int iv;
|
||||
|
@ -2795,8 +2881,8 @@ secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
|
|||
}
|
||||
}
|
||||
|
||||
secu_PrintPKCS7EncContent(out, &src->encContentInfo,
|
||||
"Encrypted Content Information", level + 1);
|
||||
return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
|
||||
"Encrypted Content Information", level + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2806,7 +2892,8 @@ secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
|
|||
static int
|
||||
secu_PrintPKCS7SignedAndEnveloped(FILE *out,
|
||||
SEC_PKCS7SignedAndEnvelopedData *src,
|
||||
const char *m, int level)
|
||||
secuPKCS7State state, const char *m,
|
||||
int level)
|
||||
{
|
||||
SECAlgorithmID *digAlg; /* pointer for digest algorithms */
|
||||
SECItem *aCert; /* pointer for certificate */
|
||||
|
@ -2842,8 +2929,10 @@ secu_PrintPKCS7SignedAndEnveloped(FILE *out,
|
|||
}
|
||||
}
|
||||
|
||||
secu_PrintPKCS7EncContent(out, &src->encContentInfo,
|
||||
"Encrypted Content Information", level + 1);
|
||||
rv = secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
|
||||
"Encrypted Content Information", level + 1);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
/* Parse and list certificates (if any) */
|
||||
if (src->rawCerts != NULL) {
|
||||
|
@ -2920,25 +3009,25 @@ SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level)
|
|||
** secu_PrintPKCS7Encrypted
|
||||
** Pretty print a PKCS7 encrypted data type (up to version 1).
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
|
||||
const char *m, int level)
|
||||
secuPKCS7State state, const char *m, int level)
|
||||
{
|
||||
SECU_Indent(out, level);
|
||||
fprintf(out, "%s:\n", m);
|
||||
SECU_PrintInteger(out, &(src->version), "Version", level + 1);
|
||||
|
||||
secu_PrintPKCS7EncContent(out, &src->encContentInfo,
|
||||
"Encrypted Content Information", level + 1);
|
||||
return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
|
||||
"Encrypted Content Information", level + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** secu_PrintPKCS7Digested
|
||||
** Pretty print a PKCS7 digested data type (up to version 1).
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
|
||||
const char *m, int level)
|
||||
secuPKCS7State state, const char *m, int level)
|
||||
{
|
||||
SECU_Indent(out, level);
|
||||
fprintf(out, "%s:\n", m);
|
||||
|
@ -2946,9 +3035,257 @@ secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
|
|||
|
||||
SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
|
||||
level + 1);
|
||||
secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
|
||||
level + 1);
|
||||
secu_PrintPKCS7ContentInfo(out, &src->contentInfo, state,
|
||||
"Content Information", level + 1);
|
||||
SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
secu_PrintPKCS12Attributes(FILE *out, SECItem *item, const char *m, int level)
|
||||
{
|
||||
SECItem my = *item;
|
||||
SECItem attribute;
|
||||
SECItem attributeID;
|
||||
SECItem attributeValues;
|
||||
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
SECU_Indent(out, level);
|
||||
fprintf(out, "%s:\n", m);
|
||||
level++;
|
||||
|
||||
while (my.len) {
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &attribute)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if ((attribute.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&attribute)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* attribute ID */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeID)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if ((attributeID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
SECU_PrintEncodedObjectID(out, &attributeID, "Attribute ID", level);
|
||||
|
||||
/* attribute values */
|
||||
if (!attribute.len) { /* skip if there aren't any */
|
||||
continue;
|
||||
}
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeValues)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (SECSuccess != SECU_StripTagAndLength(&attributeValues)) {
|
||||
return SECFailure;
|
||||
}
|
||||
while (attributeValues.len) {
|
||||
SECItem tmp;
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&attributeValues, &tmp)) {
|
||||
return SECFailure;
|
||||
}
|
||||
SECU_PrintAny(out, &tmp, NULL, level + 1);
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static int
|
||||
secu_PrintPKCS12Bag(FILE *out, SECItem *item, const char *desc, int level)
|
||||
{
|
||||
SECItem my = *item;
|
||||
SECItem bagID;
|
||||
SECItem bagValue;
|
||||
SECItem bagAttributes;
|
||||
SECOidTag bagTag;
|
||||
SECStatus rv;
|
||||
int i;
|
||||
char *m;
|
||||
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* bagId BAG-TYPE.&id ({PKCS12BagSet}) */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagID)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if ((bagID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
m = PR_smprintf("%s ID", desc);
|
||||
bagTag = SECU_PrintEncodedObjectID(out, &bagID, m ? m : "Bag ID", level);
|
||||
if (m)
|
||||
PR_smprintf_free(m);
|
||||
|
||||
/* bagValue [0] EXPLICIT BAG-TYPE.&type({PKCS12BagSet}{@bagID}) */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagValue)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if ((bagValue.data[0] & (SEC_ASN1_CLASS_MASK | SEC_ASN1_TAGNUM_MASK)) !=
|
||||
(SEC_ASN1_CONTEXT_SPECIFIC | 0)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
if (SECSuccess != SECU_StripTagAndLength(&bagValue)) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = SECSuccess;
|
||||
switch (bagTag) {
|
||||
case SEC_OID_PKCS12_V1_KEY_BAG_ID:
|
||||
/* Future we need to print out raw private keys. Not a priority since
|
||||
* p12util can't create files with unencrypted private keys, but
|
||||
* some tools can and do */
|
||||
SECU_PrintAny(out, &bagValue, "Private Key", level);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
|
||||
rv = SECU_PrintPrivateKey(out, &bagValue,
|
||||
"Encrypted Private Key", level);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_CERT_BAG_ID:
|
||||
rv = secu_PrintPKCS12Bag(out, &bagValue, "Certificate Bag", level + 1);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_CRL_BAG_ID:
|
||||
rv = secu_PrintPKCS12Bag(out, &bagValue, "Crl Bag", level + 1);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
|
||||
rv = secu_PrintPKCS12Bag(out, &bagValue, "Secret Bag", level + 1);
|
||||
break;
|
||||
/* from recursive call from CRL and certificate Bag */
|
||||
case SEC_OID_PKCS9_X509_CRL:
|
||||
case SEC_OID_PKCS9_X509_CERT:
|
||||
case SEC_OID_PKCS9_SDSI_CERT:
|
||||
/* unwrap the octect string */
|
||||
rv = SECU_StripTagAndLength(&bagValue);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
|
||||
case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
|
||||
case SEC_OID_PKCS12_SDSI_CERT_BAG:
|
||||
if (strcmp(desc, "Crl Bag") == 0) {
|
||||
rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
|
||||
(SECU_PPFunc)SECU_PrintCrl);
|
||||
} else {
|
||||
rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
|
||||
(SECU_PPFunc)SECU_PrintCertificate);
|
||||
}
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
|
||||
for (i = 1; my.len; i++) {
|
||||
SECItem nextBag;
|
||||
rv = SECU_ExtractBERAndStep(&bagValue, &nextBag);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
m = PR_smprintf("Nested Bag %d", i);
|
||||
rv = secu_PrintPKCS12Bag(out, &nextBag,
|
||||
m ? m : "Nested Bag", level + 1);
|
||||
if (m)
|
||||
PR_smprintf_free(m);
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m = PR_smprintf("%s Value", desc);
|
||||
SECU_PrintAny(out, &bagValue, m ? m : "Bag Value", level);
|
||||
if (m)
|
||||
PR_smprintf_free(m);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* bagAttributes SET OF PKCS12Attributes OPTIONAL */
|
||||
if (my.len &&
|
||||
(my.data[0] == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET))) {
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagAttributes)) {
|
||||
return SECFailure;
|
||||
}
|
||||
m = PR_smprintf("%s Attributes", desc);
|
||||
rv = secu_PrintPKCS12Attributes(out, &bagAttributes,
|
||||
m ? m : "Bag Attributes", level);
|
||||
if (m)
|
||||
PR_smprintf_free(m);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
secu_PrintPKCS7Data(FILE *out, SECItem *item, secuPKCS7State state,
|
||||
const char *desc, int level)
|
||||
{
|
||||
SECItem my = *item;
|
||||
SECItem nextbag;
|
||||
int i;
|
||||
SECStatus rv;
|
||||
|
||||
/* walk down each safe */
|
||||
switch (state) {
|
||||
case secuPKCS7PKCS12AuthSafe:
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
for (i = 1; my.len; i++) {
|
||||
char *m;
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
|
||||
return SECFailure;
|
||||
}
|
||||
m = PR_smprintf("Safe %d", i);
|
||||
rv = secu_PrintDERPKCS7ContentInfo(out, &nextbag,
|
||||
secuPKCS7PKCS12Safe,
|
||||
m ? m : "Safe", level);
|
||||
if (m)
|
||||
PR_smprintf_free(m);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
case secuPKCS7PKCS12Safe:
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
for (i = 1; my.len; i++) {
|
||||
char *m;
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
|
||||
return SECFailure;
|
||||
}
|
||||
m = PR_smprintf("Bag %d", i);
|
||||
rv = secu_PrintPKCS12Bag(out, &nextbag,
|
||||
m ? m : "Bag", level);
|
||||
if (m)
|
||||
PR_smprintf_free(m);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
case secuPKCS7Unknown:
|
||||
SECU_PrintAsHex(out, item, desc, level);
|
||||
break;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2958,7 +3295,7 @@ secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
|
|||
*/
|
||||
static int
|
||||
secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
|
||||
char *m, int level)
|
||||
secuPKCS7State state, const char *m, int level)
|
||||
{
|
||||
const char *desc;
|
||||
SECOidTag kind;
|
||||
|
@ -2973,7 +3310,7 @@ secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
|
|||
|
||||
if (src->contentTypeTag == NULL) {
|
||||
desc = "Unknown";
|
||||
kind = SEC_OID_PKCS7_DATA;
|
||||
kind = SEC_OID_UNKNOWN;
|
||||
} else {
|
||||
desc = src->contentTypeTag->desc;
|
||||
kind = src->contentTypeTag->offset;
|
||||
|
@ -2991,25 +3328,33 @@ secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
|
|||
rv = 0;
|
||||
switch (kind) {
|
||||
case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
|
||||
rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
|
||||
rv = secu_PrintPKCS7Signed(out, src->content.signedData,
|
||||
state, desc, level);
|
||||
break;
|
||||
|
||||
case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
|
||||
secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
|
||||
rv = secu_PrintPKCS7Enveloped(out, src->content.envelopedData,
|
||||
state, desc, level);
|
||||
break;
|
||||
|
||||
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
|
||||
rv = secu_PrintPKCS7SignedAndEnveloped(out,
|
||||
src->content.signedAndEnvelopedData,
|
||||
desc, level);
|
||||
state, desc, level);
|
||||
break;
|
||||
|
||||
case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
|
||||
secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
|
||||
rv = secu_PrintPKCS7Digested(out, src->content.digestedData,
|
||||
state, desc, level);
|
||||
break;
|
||||
|
||||
case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
|
||||
secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
|
||||
rv = secu_PrintPKCS7Encrypted(out, src->content.encryptedData,
|
||||
state, desc, level);
|
||||
break;
|
||||
|
||||
case SEC_OID_PKCS7_DATA:
|
||||
rv = secu_PrintPKCS7Data(out, src->content.data, state, desc, level);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -3024,8 +3369,9 @@ secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
|
|||
** SECU_PrintPKCS7ContentInfo
|
||||
** Decode and print any major PKCS7 data type (up to version 1).
|
||||
*/
|
||||
int
|
||||
SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
|
||||
static int
|
||||
secu_PrintDERPKCS7ContentInfo(FILE *out, SECItem *der, secuPKCS7State state,
|
||||
const char *m, int level)
|
||||
{
|
||||
SEC_PKCS7ContentInfo *cinfo;
|
||||
int rv;
|
||||
|
@ -3033,7 +3379,7 @@ SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
|
|||
cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (cinfo != NULL) {
|
||||
/* Send it to recursive parsing and printing module */
|
||||
rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
|
||||
rv = secu_PrintPKCS7ContentInfo(out, cinfo, state, m, level);
|
||||
SEC_PKCS7DestroyContentInfo(cinfo);
|
||||
} else {
|
||||
rv = -1;
|
||||
|
@ -3042,6 +3388,12 @@ SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
|
||||
{
|
||||
return secu_PrintDERPKCS7ContentInfo(out, der, secuPKCS7Unknown, m, level);
|
||||
}
|
||||
|
||||
/*
|
||||
** End of PKCS7 functions
|
||||
*/
|
||||
|
@ -4214,3 +4566,169 @@ cleanup:
|
|||
PORT_Free(str);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
secu_PrintPKCS12DigestInfo(FILE *out, const SECItem *t, char *m, int level)
|
||||
{
|
||||
SECItem my = *t;
|
||||
SECItem rawDigestAlgID;
|
||||
SECItem digestData;
|
||||
SECStatus rv;
|
||||
PLArenaPool *arena;
|
||||
SECAlgorithmID digestAlgID;
|
||||
char *mAlgID = NULL;
|
||||
char *mDigest = NULL;
|
||||
|
||||
/* strip the outer sequence */
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* get the algorithm ID */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &rawDigestAlgID)) {
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
#define DIGEST_ALGID_STRING "Digest Algorithm ID"
|
||||
if (m)
|
||||
mAlgID = PR_smprintf("%s " DIGEST_ALGID_STRING, m);
|
||||
rv = SEC_QuickDERDecodeItem(arena, &digestAlgID,
|
||||
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
|
||||
&rawDigestAlgID);
|
||||
if (rv == SECSuccess) {
|
||||
SECU_PrintAlgorithmID(out, &digestAlgID,
|
||||
mAlgID ? mAlgID : DIGEST_ALGID_STRING, level);
|
||||
}
|
||||
if (mAlgID)
|
||||
PR_smprintf_free(mAlgID);
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* get the mac data */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &digestData)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if ((digestData.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
#define DIGEST_STRING "Digest"
|
||||
if (m)
|
||||
mDigest = PR_smprintf("%s " DIGEST_STRING, m);
|
||||
secu_PrintOctetString(out, &digestData,
|
||||
mDigest ? mDigest : DIGEST_STRING, level);
|
||||
if (mDigest)
|
||||
PR_smprintf_free(mDigest);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
secu_PrintPKCS12MacData(FILE *out, const SECItem *t, char *m, int level)
|
||||
{
|
||||
SECItem my = *t;
|
||||
SECItem hash;
|
||||
SECItem salt;
|
||||
|
||||
if (m) {
|
||||
SECU_Indent(out, level);
|
||||
fprintf(out, "%s: \n", m);
|
||||
level++;
|
||||
}
|
||||
|
||||
/* strip the outer sequence */
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &hash)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (SECSuccess != secu_PrintPKCS12DigestInfo(out, &hash, "Mac", level)) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* handle the salt */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &salt)) {
|
||||
return SECFailure;
|
||||
;
|
||||
}
|
||||
if ((salt.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
secu_PrintOctetString(out, &salt, "Mac Salt", level);
|
||||
|
||||
if (my.len &&
|
||||
((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
|
||||
SECItem iterator;
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &iterator)) {
|
||||
return SECFailure;
|
||||
}
|
||||
SECU_PrintEncodedInteger(out, &iterator, "Iterations", level);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SECU_PrintPKCS12(FILE *out, const SECItem *t, char *m, int level)
|
||||
{
|
||||
SECItem my = *t;
|
||||
SECItem authSafe;
|
||||
SECItem macData;
|
||||
|
||||
SECU_Indent(out, level);
|
||||
fprintf(out, "%s:\n", m);
|
||||
level++;
|
||||
|
||||
/* strip the outer sequence */
|
||||
if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
|
||||
SECSuccess != SECU_StripTagAndLength(&my)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return SECFailure;
|
||||
}
|
||||
/* print and remove the optional version number */
|
||||
if (my.len && ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
|
||||
SECItem version;
|
||||
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &version)) {
|
||||
return SECFailure;
|
||||
}
|
||||
SECU_PrintEncodedInteger(out, &version, "Version", level);
|
||||
}
|
||||
|
||||
/* print the authSafe */
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &authSafe)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (SECSuccess != secu_PrintDERPKCS7ContentInfo(out, &authSafe,
|
||||
secuPKCS7PKCS12AuthSafe,
|
||||
"AuthSafe", level)) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* print the mac data (optional) */
|
||||
if (!my.len) {
|
||||
return SECSuccess;
|
||||
}
|
||||
if (SECSuccess != SECU_ExtractBERAndStep(&my, &macData)) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (SECSuccess != secu_PrintPKCS12MacData(out, &macData,
|
||||
"Mac Data", level)) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (my.len) {
|
||||
fprintf(out, "Unknown extra data found \n");
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
|
||||
#define SEC_CT_CERTIFICATE_ID "certificate-identity"
|
||||
#define SEC_CT_PKCS7 "pkcs7"
|
||||
#define SEC_CT_PKCS12 "pkcs12"
|
||||
#define SEC_CT_CRL "crl"
|
||||
#define SEC_CT_NAME "name"
|
||||
|
||||
|
@ -235,10 +236,8 @@ extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m,
|
|||
extern int SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m,
|
||||
int level);
|
||||
|
||||
#ifdef HAVE_EPV_TEMPLATE
|
||||
/* Dump contents of private key */
|
||||
extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
|
||||
#endif
|
||||
|
||||
/* Dump contents of an RSA public key */
|
||||
extern void SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
|
||||
|
@ -253,7 +252,8 @@ extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m,
|
|||
/* Pretty-print any PKCS7 thing */
|
||||
extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m,
|
||||
int level);
|
||||
|
||||
/* Pretty-print a pkcs12 file */
|
||||
extern SECStatus SECU_PrintPKCS12(FILE *out, const SECItem *der, char *m, int level);
|
||||
/* Init PKCS11 stuff */
|
||||
extern SECStatus SECU_PKCS11Init(PRBool readOnly);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nss.h"
|
||||
#include "secport.h"
|
||||
#include "secpkcs5.h"
|
||||
#include "sechash.h"
|
||||
#include "certdb.h"
|
||||
|
||||
#define PKCS12_IN_BUFFER_SIZE 200
|
||||
|
@ -43,7 +44,7 @@ Usage()
|
|||
|
||||
FPS "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n",
|
||||
progName);
|
||||
FPS "\t\t [-c key_cipher] [-C cert_cipher]\n"
|
||||
FPS "\t\t [-c key_cipher] [-C cert_cipher] [-M mac_alg]\n"
|
||||
"\t\t [-m | --key_len keyLen] [--cert_key_len certKeyLen] [-v]\n");
|
||||
FPS "\t\t [-k slotpwfile | -K slotpw]\n"
|
||||
"\t\t [-w p12filepwfile | -W p12filepw]\n");
|
||||
|
@ -625,7 +626,7 @@ p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
|
|||
|
||||
void
|
||||
P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
|
||||
SECOidTag cipher, SECOidTag certCipher,
|
||||
SECOidTag cipher, SECOidTag certCipher, SECOidTag hash,
|
||||
secuPWData *slotPw, secuPWData *p12FilePw)
|
||||
{
|
||||
SEC_PKCS12ExportContext *p12ecx = NULL;
|
||||
|
@ -690,7 +691,7 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1) !=
|
||||
if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, hash) !=
|
||||
SECSuccess) {
|
||||
SECU_PrintError(progName, "PKCS12 add password integrity failed");
|
||||
pk12uErrno = PK12UERR_PK12ADDPWDINTEG;
|
||||
|
@ -722,8 +723,8 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
|
|||
}
|
||||
|
||||
if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
|
||||
CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem, cipher) !=
|
||||
SECSuccess) {
|
||||
CERT_GetDefaultCertDB(), keySafe, NULL,
|
||||
PR_TRUE, pwitem, cipher) != SECSuccess) {
|
||||
SECU_PrintError(progName, "add cert and key failed");
|
||||
pk12uErrno = PK12UERR_ADDCERTKEY;
|
||||
goto loser;
|
||||
|
@ -857,25 +858,14 @@ loser:
|
|||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* use the oid table description to map a user input string to a particular
|
||||
* oid.
|
||||
*/
|
||||
SECOidTag
|
||||
PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
|
||||
PKCS12U_FindTagFromString(char *cipherString)
|
||||
{
|
||||
SECOidTag tag;
|
||||
SECOidData *oid;
|
||||
SECOidTag cipher;
|
||||
|
||||
/* future enhancement: accept dotted oid spec? */
|
||||
|
||||
/* future enhancement: provide 'friendlier' typed in names for
|
||||
* pbe mechanisms.
|
||||
*/
|
||||
|
||||
/* look for the oid tag by Description */
|
||||
cipher = SEC_OID_UNKNOWN;
|
||||
for (tag = 1; (oid = SECOID_FindOIDByTag(tag)) != NULL; tag++) {
|
||||
/* only interested in oids that we actually understand */
|
||||
if (oid->mechanism == CKM_INVALID_MECHANISM) {
|
||||
|
@ -884,27 +874,68 @@ PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
|
|||
if (PORT_Strcasecmp(oid->desc, cipherString) != 0) {
|
||||
continue;
|
||||
}
|
||||
/* we found a match... get the PBE version of this
|
||||
* cipher... */
|
||||
if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
|
||||
cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
|
||||
/* no eqivalent PKCS5/PKCS12 cipher, use the raw
|
||||
* encryption tag we got and pass it directly in,
|
||||
* pkcs12 will use the pkcsv5 mechanism */
|
||||
if (cipher == SEC_OID_PKCS5_PBES2) {
|
||||
cipher = tag;
|
||||
} else if (cipher == SEC_OID_PKCS5_PBMAC1) {
|
||||
/* make sure we have not macing ciphers here */
|
||||
cipher = SEC_OID_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
return tag;
|
||||
}
|
||||
return SEC_OID_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* use the oid table description to map a user input string to a particular
|
||||
* oid.
|
||||
*/
|
||||
SECOidTag
|
||||
PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
|
||||
{
|
||||
SECOidTag tag;
|
||||
SECOidTag cipher;
|
||||
|
||||
/* future enhancement: provide 'friendlier' typed in names for
|
||||
* pbe mechanisms.
|
||||
*/
|
||||
|
||||
/* look for the oid tag by Description */
|
||||
tag = PKCS12U_FindTagFromString(cipherString);
|
||||
if (tag == SEC_OID_UNKNOWN) {
|
||||
return tag;
|
||||
}
|
||||
|
||||
cipher = SEC_OID_UNKNOWN;
|
||||
/* we found a match... get the PBE version of this
|
||||
* cipher... */
|
||||
if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
|
||||
cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
|
||||
/* no eqivalent PKCS5/PKCS12 cipher, use the raw
|
||||
* encryption tag we got and pass it directly in,
|
||||
* pkcs12 will use the pkcsv5 mechanism */
|
||||
if (cipher == SEC_OID_PKCS5_PBES2) {
|
||||
cipher = tag;
|
||||
} else if (cipher == SEC_OID_PKCS5_PBMAC1) {
|
||||
/* make sure we have not macing ciphers here */
|
||||
cipher = SEC_OID_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
cipher = tag;
|
||||
}
|
||||
return cipher;
|
||||
}
|
||||
|
||||
SECOidTag
|
||||
PKCS12U_MapHashFromString(char *hashString)
|
||||
{
|
||||
SECOidTag hashAlg;
|
||||
|
||||
/* look for the oid tag by Description */
|
||||
hashAlg = PKCS12U_FindTagFromString(hashString);
|
||||
if (hashAlg == SEC_OID_UNKNOWN) {
|
||||
return hashAlg;
|
||||
}
|
||||
/* make sure it's a hashing oid */
|
||||
if (HASH_GetHashTypeByOidTag(hashAlg) == HASH_AlgNULL) {
|
||||
return SEC_OID_UNKNOWN;
|
||||
}
|
||||
return hashAlg;
|
||||
}
|
||||
|
||||
static void
|
||||
p12u_EnableAllCiphers()
|
||||
{
|
||||
|
@ -917,7 +948,7 @@ p12u_EnableAllCiphers()
|
|||
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
|
||||
SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
|
||||
SEC_PKCS12SetPreferredCipher(PKCS12_AES_CBC_256, 1);
|
||||
}
|
||||
|
||||
static PRUintn
|
||||
|
@ -963,7 +994,8 @@ enum {
|
|||
opt_Cipher,
|
||||
opt_CertCipher,
|
||||
opt_KeyLength,
|
||||
opt_CertKeyLength
|
||||
opt_CertKeyLength,
|
||||
opt_Mac
|
||||
};
|
||||
|
||||
static secuCommandFlag pk12util_options[] =
|
||||
|
@ -984,7 +1016,8 @@ static secuCommandFlag pk12util_options[] =
|
|||
{ /* opt_Cipher */ 'c', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_CertCipher */ 'C', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_KeyLength */ 'm', PR_TRUE, 0, PR_FALSE, "key_len" },
|
||||
{ /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" }
|
||||
{ /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" },
|
||||
{ /* opt_Mac */ 'M', PR_TRUE, 0, PR_FALSE, PR_FALSE }
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -998,9 +1031,9 @@ main(int argc, char **argv)
|
|||
char *export_file = NULL;
|
||||
char *dbprefix = "";
|
||||
SECStatus rv;
|
||||
SECOidTag cipher =
|
||||
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
|
||||
SECOidTag certCipher;
|
||||
SECOidTag cipher = SEC_OID_AES_256_CBC;
|
||||
SECOidTag hash = SEC_OID_SHA256;
|
||||
SECOidTag certCipher = SEC_OID_AES_128_CBC;
|
||||
int keyLen = 0;
|
||||
int certKeyLen = 0;
|
||||
secuCommand pk12util;
|
||||
|
@ -1114,7 +1147,6 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
certCipher = PK11_IsFIPS() ? SEC_OID_UNKNOWN : SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
|
||||
if (pk12util.options[opt_CertCipher].activated) {
|
||||
char *cipherString = pk12util.options[opt_CertCipher].arg;
|
||||
|
||||
|
@ -1132,6 +1164,18 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (pk12util.options[opt_Mac].activated) {
|
||||
char *hashString = pk12util.options[opt_Mac].arg;
|
||||
|
||||
hash = PKCS12U_MapHashFromString(hashString);
|
||||
/* We don't support creating Mac-less pkcs 12 files */
|
||||
if (hash == SEC_OID_UNKNOWN) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);
|
||||
pk12uErrno = PK12UERR_INVALIDALGORITHM;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (pk12util.options[opt_Import].activated) {
|
||||
P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw);
|
||||
|
@ -1139,7 +1183,7 @@ main(int argc, char **argv)
|
|||
} else if (pk12util.options[opt_Export].activated) {
|
||||
P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
|
||||
export_file, slot, cipher, certCipher,
|
||||
&slotPw, &p12FilePw);
|
||||
hash, &slotPw, &p12FilePw);
|
||||
|
||||
} else if (pk12util.options[opt_List].activated) {
|
||||
P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw);
|
||||
|
|
|
@ -27,14 +27,13 @@ Usage(char *progName)
|
|||
progName);
|
||||
fprintf(stderr, "Pretty prints a file containing ASN.1 data in DER or ascii format.\n");
|
||||
fprintf(stderr, "%-14s Specify input and display type:", "-t type");
|
||||
#ifdef HAVE_EPV_TEMPLATE
|
||||
fprintf(stderr, " %s (sk),", SEC_CT_PRIVATE_KEY);
|
||||
#endif
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "%-14s %s (pk), %s (c), %s (cr),\n", "", SEC_CT_PUBLIC_KEY,
|
||||
SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
|
||||
fprintf(stderr, "%-14s %s (ci), %s (p7), %s or %s (n).\n", "", SEC_CT_CERTIFICATE_ID,
|
||||
SEC_CT_PKCS7, SEC_CT_CRL, SEC_CT_NAME);
|
||||
fprintf(stderr, "%-14s %s (ci), %s (p7), %s (p12), %s or %s (n).\n", "",
|
||||
SEC_CT_CERTIFICATE_ID, SEC_CT_PKCS7, SEC_CT_PKCS12,
|
||||
SEC_CT_CRL, SEC_CT_NAME);
|
||||
fprintf(stderr, "%-14s (Use either the long type name or the shortcut.)\n", "");
|
||||
fprintf(stderr, "%-14s Input is in ascii encoded form (RFC1113)\n",
|
||||
"-a");
|
||||
|
@ -159,11 +158,9 @@ main(int argc, char **argv)
|
|||
SECU_PrintCertificateRequest);
|
||||
} else if (PORT_Strcmp(typeTag, SEC_CT_CRL) == 0) {
|
||||
rv = SECU_PrintSignedData(outFile, &data, "CRL", 0, SECU_PrintCrl);
|
||||
#ifdef HAVE_EPV_TEMPLATE
|
||||
} else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0 ||
|
||||
PORT_Strcmp(typeTag, "sk") == 0) {
|
||||
rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
|
||||
#endif
|
||||
} else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0 ||
|
||||
PORT_Strcmp(typeTag, "pk") == 0) {
|
||||
rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0);
|
||||
|
@ -174,6 +171,9 @@ main(int argc, char **argv)
|
|||
} else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0 ||
|
||||
PORT_Strcmp(typeTag, "n") == 0) {
|
||||
rv = SECU_PrintDERName(outFile, &data, "Name", 0);
|
||||
} else if (PORT_Strcmp(typeTag, SEC_CT_PKCS12) == 0 ||
|
||||
PORT_Strcmp(typeTag, "p12") == 0) {
|
||||
rv = SECU_PrintPKCS12(outFile, &data, "PKCS #12 File", 0);
|
||||
} else {
|
||||
fprintf(stderr, "%s: don't know how to print out '%s' files\n",
|
||||
progName, typeTag);
|
||||
|
|
|
@ -1894,16 +1894,23 @@ configureEchWithPublicName(PRFileDesc *model_sock, const char *public_name)
|
|||
SECKEYPrivateKey *privKey = NULL;
|
||||
SECOidData *oidData;
|
||||
char *echConfigBase64 = NULL;
|
||||
PRUint8 configId = 0;
|
||||
PRUint8 configBuf[1000];
|
||||
unsigned int len = 0;
|
||||
unsigned int echCipherSuite = ((unsigned int)HpkeKdfHkdfSha256 << 16) |
|
||||
HpkeAeadChaCha20Poly1305;
|
||||
HpkeSymmetricSuite echCipherSuite = { HpkeKdfHkdfSha256,
|
||||
HpkeAeadChaCha20Poly1305 };
|
||||
|
||||
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
|
||||
if (!slot) {
|
||||
errWarn("PK11_GetInternalKeySlot failed");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (PK11_GenerateRandom(&configId, sizeof(configId)) != SECSuccess) {
|
||||
errWarn("Failed to generate random configId");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
oidData = SECOID_FindOIDByTag(SEC_OID_CURVE25519);
|
||||
if (oidData && (2 + oidData->oid.len) < sizeof(paramBuf)) {
|
||||
ecParams.data[0] = SEC_ASN1_OBJECT_ID;
|
||||
|
@ -1916,16 +1923,17 @@ configureEchWithPublicName(PRFileDesc *model_sock, const char *public_name)
|
|||
}
|
||||
privKey = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ecParams,
|
||||
&pubKey, PR_FALSE, PR_FALSE, NULL);
|
||||
|
||||
if (!privKey || !pubKey) {
|
||||
errWarn("Failed to generate ECH keypair");
|
||||
goto loser;
|
||||
}
|
||||
rv = SSL_EncodeEchConfig(echParamsStr, &echCipherSuite, 1,
|
||||
HpkeDhKemX25519Sha256, pubKey, 50,
|
||||
configBuf, &len, sizeof(configBuf));
|
||||
|
||||
rv = SSL_EncodeEchConfigId(configId, echParamsStr, 100,
|
||||
HpkeDhKemX25519Sha256, pubKey,
|
||||
&echCipherSuite, 1,
|
||||
configBuf, &len, sizeof(configBuf));
|
||||
if (rv != SECSuccess) {
|
||||
errWarn("SSL_EncodeEchConfig failed");
|
||||
errWarn("SSL_EncodeEchConfigId failed");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
|
|
|
@ -573,11 +573,6 @@
|
|||
'NSS_DISABLE_DBM',
|
||||
],
|
||||
}],
|
||||
[ 'enable_draft_hpke==1', {
|
||||
'defines': [
|
||||
'NSS_ENABLE_DRAFT_HPKE',
|
||||
],
|
||||
}],
|
||||
[ 'disable_libpkix==1', {
|
||||
'defines': [
|
||||
'NSS_DISABLE_LIBPKIX',
|
||||
|
|
|
@ -195,10 +195,6 @@ ifdef NSS_PKIX_NO_LDAP
|
|||
DEFINES += -DNSS_PKIX_NO_LDAP
|
||||
endif
|
||||
|
||||
ifdef NSS_ENABLE_DRAFT_HPKE
|
||||
DEFINES += -DNSS_ENABLE_DRAFT_HPKE
|
||||
endif
|
||||
|
||||
# FIPS support requires startup tests to be executed at load time of shared modules.
|
||||
# For performance reasons, these tests are disabled by default.
|
||||
# When compiling binaries that must support FIPS mode,
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -28,11 +28,17 @@
|
|||
<cmdsynopsis>
|
||||
<command>pk12util</command>
|
||||
<arg>-i p12File|-l p12File|-o p12File</arg>
|
||||
<arg>-c keyCipher</arg>
|
||||
<arg>-C certCipher</arg>
|
||||
<arg>-d [sql:]directory</arg>
|
||||
<arg>-h tokenname</arg>
|
||||
<arg>-m | --key-len keyLength</arg>
|
||||
<arg>-M hashAlg</arg>
|
||||
<arg>-n certname</arg>
|
||||
<arg>-P dbprefix</arg>
|
||||
<arg>-r</arg>
|
||||
<arg>-v</arg>
|
||||
<arg>--cert-key-len certKeyLength</arg>
|
||||
<arg>-k slotPasswordFile|-K slotPassword</arg>
|
||||
<arg>-w p12filePasswordFile|-W p12filePassword</arg>
|
||||
</cmdsynopsis>
|
||||
|
@ -107,6 +113,12 @@
|
|||
<listitem><para>Specify the desired length of the symmetric key to be used to encrypt the private key.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-M hashAlg</term>
|
||||
<listitem><para>Specify the hash algorithm used in the pkcs #12 mac. This algorithm also specifies the HMAC used in the prf when using pkcs #5 v2.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>--cert-key-len certKeyLength</term>
|
||||
<listitem><para>Specify the desired length of the symmetric key to be used to encrypt the certificates and other meta-data.</para></listitem>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<title>Description</title>
|
||||
|
||||
<para><command>pp </command>pretty-prints private and public key, certificate, certificate-request,
|
||||
pkcs7 or crl files
|
||||
pkcs7, pkcs12 or crl files
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<varlistentry>
|
||||
<term><option>-t </option> <replaceable>type</replaceable></term>
|
||||
<listitem>
|
||||
<simpara>specify the input, one of {private-key | public-key | certificate | certificate-request | pkcs7 | crl}</simpara>
|
||||
<simpara>specify the input, one of {private-key | public-key | certificate | certificate-request | pkcs7 | pkcs12 | crl | name}</simpara>
|
||||
<simpara></simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python3
|
||||
# This script converts the test vectors referenced by the specification into
|
||||
# a form that matches our implementation.
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def pkcs8(sk, pk):
|
||||
print(
|
||||
f'"3067020100301406072a8648ce3d020106092b06010401da470f01044c304a0201010420{sk}a123032100{pk}",'
|
||||
)
|
||||
|
||||
|
||||
i = 0
|
||||
for tc in json.load(sys.stdin):
|
||||
# Only mode_base and mode_psk
|
||||
if tc["mode"] != 0 and tc["mode"] != 1:
|
||||
continue
|
||||
# X25519
|
||||
if tc["kem_id"] != 32:
|
||||
continue
|
||||
# SHA-2 256, 384, and 512 (1..3)
|
||||
if not tc["kdf_id"] in [1, 2, 3]:
|
||||
continue
|
||||
# AES-128-GCM, AES-256-GCM, and ChaCha20Poly1305 (1..3 also)
|
||||
if not tc["aead_id"] in [1, 2, 3]:
|
||||
continue
|
||||
|
||||
print(f"{{{i},")
|
||||
print(f"static_cast<HpkeModeId>({tc['mode']}),")
|
||||
print(f"static_cast<HpkeKemId>({tc['kem_id']}),")
|
||||
print(f"static_cast<HpkeKdfId>({tc['kdf_id']}),")
|
||||
print(f"static_cast<HpkeAeadId>({tc['aead_id']}),")
|
||||
print(f'"{tc["info"]}", // info')
|
||||
pkcs8(tc["skEm"], tc["pkEm"])
|
||||
pkcs8(tc["skRm"], tc["pkRm"])
|
||||
print(f'"{tc.get("psk", "")}", // psk')
|
||||
print(f'"{tc.get("psk_id", "")}", // psk_id')
|
||||
print(f'"{tc["enc"]}", // enc')
|
||||
print(f'"{tc["key"]}", // key')
|
||||
print(f'"{tc["base_nonce"]}", // nonce')
|
||||
|
||||
print("{ // Encryptions")
|
||||
for e in tc["encryptions"]:
|
||||
print("{")
|
||||
print(f'"{e["plaintext"]}", // pt')
|
||||
print(f'"{e["aad"]}", // aad')
|
||||
print(f'"{e["ciphertext"]}", // ct')
|
||||
print("},")
|
||||
print("},")
|
||||
|
||||
print("{ // Exports")
|
||||
for e in tc["exports"]:
|
||||
print("{")
|
||||
print(f'"{e["exporter_context"]}", // context')
|
||||
print(f'{e["L"]}, // len')
|
||||
print(f'"{e["exported_value"]}", // exported')
|
||||
print("},")
|
||||
print("},")
|
||||
print("},")
|
||||
i = i + 1
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,6 +4,8 @@
|
|||
* 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 UNSAFE_FUZZER_MODE // See Bug 1709750
|
||||
|
||||
#include <memory>
|
||||
#include "blapi.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
@ -19,7 +21,6 @@
|
|||
namespace nss_test {
|
||||
|
||||
/* See note in pk11pub.h. */
|
||||
#ifdef NSS_ENABLE_DRAFT_HPKE
|
||||
#include "cpputil.h"
|
||||
|
||||
class HpkeTest {
|
||||
|
@ -682,14 +683,7 @@ TEST_F(ModeParameterizedTest, InvalidReceiverKeyType) {
|
|||
pub_key.get(), &info_item));
|
||||
EXPECT_EQ(SEC_ERROR_BAD_KEY, PORT_GetError());
|
||||
}
|
||||
#else
|
||||
TEST(HpkeTest, EnsureNotImplemented) {
|
||||
ScopedHpkeContext cx(
|
||||
PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256,
|
||||
HpkeAeadChaCha20Poly1305, nullptr, nullptr));
|
||||
EXPECT_FALSE(cx.get());
|
||||
EXPECT_EQ(SEC_ERROR_INVALID_ALGORITHM, PORT_GetError());
|
||||
}
|
||||
#endif // NSS_ENABLE_DRAFT_HPKE
|
||||
|
||||
} // namespace nss_test
|
||||
|
||||
#endif
|
||||
|
|
|
@ -497,24 +497,3 @@ SECStatus SSLInt_SetRawEchConfigForRetry(PRFileDesc *fd, const uint8_t *buf,
|
|||
PORT_Memcpy(cfg->raw.data, buf, len);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
// Zero the echConfig.config_id for all configured echConfigs.
|
||||
// This mimics a collision on the 8B config ID so that we can
|
||||
// test trial decryption.
|
||||
SECStatus SSLInt_ZeroEchConfigIds(PRFileDesc *fd) {
|
||||
if (!fd) {
|
||||
return SECFailure;
|
||||
}
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
for (PRCList *cur_p = PR_LIST_HEAD(&ss->echConfigs); cur_p != &ss->echConfigs;
|
||||
cur_p = PR_NEXT_LINK(cur_p)) {
|
||||
PORT_Memset(((sslEchConfig *)cur_p)->configId, 0,
|
||||
sizeof(((sslEchConfig *)cur_p)->configId));
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
@ -51,5 +51,4 @@ SECStatus SSLInt_SetDCAdvertisedSigSchemes(PRFileDesc *fd,
|
|||
SECStatus SSLInt_RemoveServerCertificates(PRFileDesc *fd);
|
||||
SECStatus SSLInt_SetRawEchConfigForRetry(PRFileDesc *fd, const uint8_t *buf,
|
||||
size_t len);
|
||||
SECStatus SSLInt_ZeroEchConfigIds(PRFileDesc *fd);
|
||||
#endif // ifndef libssl_internals_h_
|
||||
|
|
|
@ -660,7 +660,6 @@ TEST_P(TlsConnectGeneric, ClientAuthEcdsa) {
|
|||
CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
|
||||
}
|
||||
|
||||
#ifdef NSS_ENABLE_DRAFT_HPKE
|
||||
TEST_P(TlsConnectGeneric, ClientAuthWithEch) {
|
||||
Reset(TlsAgent::kServerEcdsa256);
|
||||
EnsureTlsSetup();
|
||||
|
@ -670,7 +669,6 @@ TEST_P(TlsConnectGeneric, ClientAuthWithEch) {
|
|||
Connect();
|
||||
CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_P(TlsConnectGeneric, ClientAuthBigRsa) {
|
||||
Reset(TlsAgent::kServerRsa, TlsAgent::kRsa2048);
|
||||
|
|
|
@ -214,7 +214,6 @@ TEST_F(Tls13CompatTest, EnabledHrrZeroRtt) {
|
|||
CheckForCompatHandshake();
|
||||
}
|
||||
|
||||
#ifdef NSS_ENABLE_DRAFT_HPKE
|
||||
TEST_F(Tls13CompatTest, EnabledAcceptedEch) {
|
||||
EnsureTlsSetup();
|
||||
SetupEch(client_, server_);
|
||||
|
@ -237,7 +236,6 @@ TEST_F(Tls13CompatTest, EnabledRejectedEch) {
|
|||
// Reset expectations for the TlsAgent dtor.
|
||||
server_->ExpectReceiveAlert(kTlsAlertCloseNotify, kTlsAlertWarning);
|
||||
}
|
||||
#endif
|
||||
|
||||
class TlsSessionIDEchoFilter : public TlsHandshakeFilter {
|
||||
public:
|
||||
|
|
|
@ -262,7 +262,7 @@ void TlsConnectTestBase::MakeEcKeyParams(SECItem* params, SSLNamedGroup group) {
|
|||
}
|
||||
|
||||
void TlsConnectTestBase::GenerateEchConfig(
|
||||
HpkeKemId kem_id, const std::vector<uint32_t>& cipher_suites,
|
||||
HpkeKemId kem_id, const std::vector<HpkeSymmetricSuite>& cipher_suites,
|
||||
const std::string& public_name, uint16_t max_name_len, DataBuffer& record,
|
||||
ScopedSECKEYPublicKey& pubKey, ScopedSECKEYPrivateKey& privKey) {
|
||||
bool gen_keys = !pubKey && !privKey;
|
||||
|
@ -282,9 +282,9 @@ void TlsConnectTestBase::GenerateEchConfig(
|
|||
SECITEM_FreeItem(&ecParams, PR_FALSE);
|
||||
PRUint8 encoded[1024];
|
||||
unsigned int encoded_len = 0;
|
||||
SECStatus rv = SSL_EncodeEchConfig(
|
||||
public_name.c_str(), cipher_suites.data(), cipher_suites.size(), kem_id,
|
||||
pub, max_name_len, encoded, &encoded_len, sizeof(encoded));
|
||||
SECStatus rv = SSL_EncodeEchConfigId(
|
||||
77, public_name.c_str(), max_name_len, kem_id, pub, cipher_suites.data(),
|
||||
cipher_suites.size(), encoded, &encoded_len, sizeof(encoded));
|
||||
EXPECT_EQ(SECSuccess, rv);
|
||||
EXPECT_GT(encoded_len, 0U);
|
||||
|
||||
|
@ -305,10 +305,9 @@ void TlsConnectTestBase::SetupEch(std::shared_ptr<TlsAgent>& client,
|
|||
ScopedSECKEYPublicKey pub;
|
||||
ScopedSECKEYPrivateKey priv;
|
||||
DataBuffer record;
|
||||
static const std::vector<uint32_t> kDefaultSuites = {
|
||||
(static_cast<uint16_t>(HpkeKdfHkdfSha256) << 16) |
|
||||
HpkeAeadChaCha20Poly1305,
|
||||
(static_cast<uint16_t>(HpkeKdfHkdfSha256) << 16) | HpkeAeadAes128Gcm};
|
||||
static const std::vector<HpkeSymmetricSuite> kDefaultSuites = {
|
||||
{HpkeKdfHkdfSha256, HpkeAeadChaCha20Poly1305},
|
||||
{HpkeKdfHkdfSha256, HpkeAeadAes128Gcm}};
|
||||
|
||||
GenerateEchConfig(kem_id, kDefaultSuites, "public.name", 100, record, pub,
|
||||
priv);
|
||||
|
|
|
@ -147,12 +147,10 @@ class TlsConnectTestBase : public ::testing::Test {
|
|||
void RestoreAlgorithmPolicy();
|
||||
|
||||
static void MakeEcKeyParams(SECItem* params, SSLNamedGroup group);
|
||||
static void GenerateEchConfig(HpkeKemId kem_id,
|
||||
const std::vector<uint32_t>& cipher_suites,
|
||||
const std::string& public_name,
|
||||
uint16_t max_name_len, DataBuffer& record,
|
||||
ScopedSECKEYPublicKey& pubKey,
|
||||
ScopedSECKEYPrivateKey& privKey);
|
||||
static void GenerateEchConfig(
|
||||
HpkeKemId kem_id, const std::vector<HpkeSymmetricSuite>& cipher_suites,
|
||||
const std::string& public_name, uint16_t max_name_len, DataBuffer& record,
|
||||
ScopedSECKEYPublicKey& pubKey, ScopedSECKEYPrivateKey& privKey);
|
||||
void SetupEch(std::shared_ptr<TlsAgent>& client,
|
||||
std::shared_ptr<TlsAgent>& server,
|
||||
HpkeKemId kem_id = HpkeDhKemX25519Sha256,
|
||||
|
|
|
@ -31,23 +31,22 @@ class TlsAgentEchTest : public TlsAgentTestClient13 {
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef NSS_ENABLE_DRAFT_HPKE
|
||||
#include "cpputil.h" // Unused function error if included without HPKE.
|
||||
|
||||
static std::string kPublicName("public.name");
|
||||
|
||||
static const std::vector<uint32_t> kDefaultSuites = {
|
||||
(static_cast<uint32_t>(HpkeKdfHkdfSha256) << 16) | HpkeAeadChaCha20Poly1305,
|
||||
(static_cast<uint32_t>(HpkeKdfHkdfSha256) << 16) | HpkeAeadAes128Gcm};
|
||||
static const std::vector<uint32_t> kSuiteChaCha = {
|
||||
(static_cast<uint32_t>(HpkeKdfHkdfSha256) << 16) |
|
||||
HpkeAeadChaCha20Poly1305};
|
||||
static const std::vector<uint32_t> kSuiteAes = {
|
||||
(static_cast<uint32_t>(HpkeKdfHkdfSha256) << 16) | HpkeAeadAes128Gcm};
|
||||
std::vector<uint32_t> kBogusSuite = {0xfefefefe};
|
||||
static const std::vector<uint32_t> kUnknownFirstSuite = {
|
||||
0xfefefefe,
|
||||
(static_cast<uint32_t>(HpkeKdfHkdfSha256) << 16) | HpkeAeadAes128Gcm};
|
||||
static const std::vector<HpkeSymmetricSuite> kDefaultSuites = {
|
||||
{HpkeKdfHkdfSha256, HpkeAeadChaCha20Poly1305},
|
||||
{HpkeKdfHkdfSha256, HpkeAeadAes128Gcm}};
|
||||
static const std::vector<HpkeSymmetricSuite> kSuiteChaCha = {
|
||||
{HpkeKdfHkdfSha256, HpkeAeadChaCha20Poly1305}};
|
||||
static const std::vector<HpkeSymmetricSuite> kSuiteAes = {
|
||||
{HpkeKdfHkdfSha256, HpkeAeadAes128Gcm}};
|
||||
std::vector<HpkeSymmetricSuite> kBogusSuite = {
|
||||
{static_cast<HpkeKdfId>(0xfefe), static_cast<HpkeAeadId>(0xfefe)}};
|
||||
static const std::vector<HpkeSymmetricSuite> kUnknownFirstSuite = {
|
||||
{static_cast<HpkeKdfId>(0xfefe), static_cast<HpkeAeadId>(0xfefe)},
|
||||
{HpkeKdfHkdfSha256, HpkeAeadAes128Gcm}};
|
||||
|
||||
class TlsConnectStreamTls13Ech : public TlsConnectTestBase {
|
||||
public:
|
||||
|
@ -150,7 +149,7 @@ class TlsConnectStreamTls13Ech : public TlsConnectTestBase {
|
|||
ADD_FAILURE() << "No slot";
|
||||
return;
|
||||
}
|
||||
std::vector<uint8_t> pkcs8_r = hex_string_to_bytes(kFixedServerPubkey);
|
||||
std::vector<uint8_t> pkcs8_r = hex_string_to_bytes(kFixedServerKey);
|
||||
SECItem pkcs8_r_item = {siBuffer, toUcharPtr(pkcs8_r.data()),
|
||||
static_cast<unsigned int>(pkcs8_r.size())};
|
||||
|
||||
|
@ -164,18 +163,6 @@ class TlsConnectStreamTls13Ech : public TlsConnectTestBase {
|
|||
ASSERT_NE(nullptr, tmp_pub);
|
||||
}
|
||||
|
||||
private:
|
||||
// Testing certan invalid CHInner configurations is tricky, particularly
|
||||
// since the CHOuter forms AAD and isn't available in filters. Instead of
|
||||
// generating these inputs on the fly, use a fixed server keypair so that
|
||||
// the input can be generated once (e.g. via a debugger) and replayed in
|
||||
// each invocation of the test.
|
||||
std::string kFixedServerPubkey =
|
||||
"3067020100301406072a8648ce3d020106092b06010401da470f01044c304a"
|
||||
"02010104205a8aa0d2476b28521588e0c704b14db82cdd4970d340d293a957"
|
||||
"6deaee9ec1c7a1230321008756e2580c07c1d2ffcb662f5fadc6d6ff13da85"
|
||||
"abd7adfecf984aaa102c1269";
|
||||
|
||||
void SetMutualEchConfigs(ScopedSECKEYPublicKey& pub,
|
||||
ScopedSECKEYPrivateKey& priv) {
|
||||
DataBuffer echconfig;
|
||||
|
@ -189,6 +176,18 @@ class TlsConnectStreamTls13Ech : public TlsConnectTestBase {
|
|||
SSL_SetClientEchConfigs(client_->ssl_fd(), echconfig.data(),
|
||||
echconfig.len()));
|
||||
}
|
||||
|
||||
private:
|
||||
// Testing certan invalid CHInner configurations is tricky, particularly
|
||||
// since the CHOuter forms AAD and isn't available in filters. Instead of
|
||||
// generating these inputs on the fly, use a fixed server keypair so that
|
||||
// the input can be generated once (e.g. via a debugger) and replayed in
|
||||
// each invocation of the test.
|
||||
std::string kFixedServerKey =
|
||||
"3067020100301406072a8648ce3d020106092b06010401da470f01044c304a"
|
||||
"02010104205a8aa0d2476b28521588e0c704b14db82cdd4970d340d293a957"
|
||||
"6deaee9ec1c7a1230321008756e2580c07c1d2ffcb662f5fadc6d6ff13da85"
|
||||
"abd7adfecf984aaa102c1269";
|
||||
};
|
||||
|
||||
static void CheckCertVerifyPublicName(TlsAgent* agent) {
|
||||
|
@ -226,10 +225,10 @@ TEST_P(TlsAgentEchTest, EchConfigsSupportedYesNo) {
|
|||
|
||||
// ECHConfig 2 cipher_suites are unsupported.
|
||||
const std::string mixed =
|
||||
"0086FE09003F000B7075626C69632E6E616D6500203BB6D46C201B820F1AE4AFD4DEC304"
|
||||
"444156E4E04D1BF0FFDA7783B6B457F75600200008000100030001000100640000FE0900"
|
||||
"3F000B7075626C69632E6E616D6500203BB6D46C201B820F1AE4AFD4DEC304444156E4E0"
|
||||
"4D1BF0FFDA7783B6B457F756002000080001FFFFFFFF000100640000";
|
||||
"0088FE0A004000002000203BB6D46C201B820F1AE4AFD4DEC304444156E4E04D1BF0FFDA"
|
||||
"7783B6B457F756000800010003000100010064000B7075626C69632E6E616D650000FE0A"
|
||||
"004000002000203BB6D46C201B820F1AE4AFD4DEC304444156E4E04D1BF0FFDA7783B6B4"
|
||||
"57F75600080001FFFFFFFF00010064000B7075626C69632E6E616D650000";
|
||||
std::vector<uint8_t> config = hex_string_to_bytes(mixed);
|
||||
DataBuffer echconfig(config.data(), config.size());
|
||||
|
||||
|
@ -251,10 +250,10 @@ TEST_P(TlsAgentEchTest, EchConfigsSupportedNoYes) {
|
|||
|
||||
// ECHConfig 1 cipher_suites are unsupported.
|
||||
const std::string mixed =
|
||||
"0086FE09003F000B7075626C69632E6E616D6500203BB6D46C201B820F1AE4AFD4DEC304"
|
||||
"444156E4E04D1BF0FFDA7783B6B457F756002000080001FFFFFFFF000100640000FE0900"
|
||||
"3F000B7075626C69632E6E616D6500203BB6D46C201B820F1AE4AFD4DEC304444156E4E0"
|
||||
"4D1BF0FFDA7783B6B457F75600200008000100030001000100640000";
|
||||
"0088FE0A004000002000203BB6D46C201B820F1AE4AFD4DEC304444156E4E04D1BF0FFDA"
|
||||
"7783B6B457F75600080001FFFFFFFF00010064000B7075626C69632E6E616D650000FE0A"
|
||||
"004000002000203BB6D46C201B820F1AE4AFD4DEC304444156E4E04D1BF0FFDA7783B6B4"
|
||||
"57F756000800010003000100010064000B7075626C69632E6E616D650000";
|
||||
std::vector<uint8_t> config = hex_string_to_bytes(mixed);
|
||||
DataBuffer echconfig(config.data(), config.size());
|
||||
|
||||
|
@ -276,10 +275,10 @@ TEST_P(TlsAgentEchTest, EchConfigsSupportedNoNo) {
|
|||
|
||||
// ECHConfig 1 and 2 cipher_suites are unsupported.
|
||||
const std::string unsupported =
|
||||
"0086FE09003F000B7075626C69632E6E616D6500203BB6D46C201B820F1AE4AFD4DEC304"
|
||||
"444156E4E04D1BF0FFDA7783B6B457F756002000080001FFFF0001FFFF00640000FE0900"
|
||||
"3F000B7075626C69632E6E616D6500203BB6D46C201B820F1AE4AFD4DEC304444156E4E0"
|
||||
"4D1BF0FFDA7783B6B457F75600200008FFFF0003FFFF000100640000";
|
||||
"0088FE0A004000002000203BB6D46C201B820F1AE4AFD4DEC304444156E4E04D1BF0FFDA"
|
||||
"7783B6B457F75600080001FFFF0001FFFF0064000B7075626C69632E6E616D650000FE0A"
|
||||
"004000002000203BB6D46C201B820F1AE4AFD4DEC304444156E4E04D1BF0FFDA7783B6B4"
|
||||
"57F7560008FFFF0003FFFF00010064000B7075626C69632E6E616D650000";
|
||||
std::vector<uint8_t> config = hex_string_to_bytes(unsupported);
|
||||
DataBuffer echconfig(config.data(), config.size());
|
||||
|
||||
|
@ -355,7 +354,7 @@ TEST_P(TlsAgentEchTest, UnsupportedHpkeKem) {
|
|||
ScopedSECKEYPublicKey pub;
|
||||
ScopedSECKEYPrivateKey priv;
|
||||
DataBuffer echconfig;
|
||||
// SSL_EncodeEchConfig encodes without validation.
|
||||
// SSL_EncodeEchConfigId encodes without validation.
|
||||
TlsConnectTestBase::GenerateEchConfig(static_cast<HpkeKemId>(0xff),
|
||||
kDefaultSuites, kPublicName, 100,
|
||||
echconfig, pub, priv);
|
||||
|
@ -452,50 +451,50 @@ TEST_P(TlsAgentEchTest, ApiInvalidArgs) {
|
|||
// GetRetries
|
||||
EXPECT_EQ(SECFailure, SSL_GetEchRetryConfigs(agent_->ssl_fd(), nullptr));
|
||||
|
||||
// EncodeEchConfig
|
||||
// EncodeEchConfigId
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig(nullptr, reinterpret_cast<uint32_t*>(1), 1,
|
||||
static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<uint32_t*>(1), 1));
|
||||
SSL_EncodeEchConfigId(0, nullptr, 1, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1),
|
||||
reinterpret_cast<HpkeSymmetricSuite*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<unsigned int*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig("name", nullptr, 1, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<uint32_t*>(1), 1));
|
||||
SSL_EncodeEchConfigId(0, "name", 1, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1),
|
||||
nullptr, 1, reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<unsigned int*>(1), 1));
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig("name", reinterpret_cast<uint32_t*>(1), 0,
|
||||
static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<uint32_t*>(1), 1));
|
||||
SSL_EncodeEchConfigId(0, "name", 1, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1),
|
||||
reinterpret_cast<HpkeSymmetricSuite*>(1), 0,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<unsigned int*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure, SSL_EncodeEchConfigId(
|
||||
0, "name", 1, static_cast<HpkeKemId>(1), nullptr,
|
||||
reinterpret_cast<HpkeSymmetricSuite*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<unsigned int*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig("name", reinterpret_cast<uint32_t*>(1), 1,
|
||||
static_cast<HpkeKemId>(1), nullptr, 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<uint32_t*>(1), 1));
|
||||
SSL_EncodeEchConfigId(0, nullptr, 0, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1),
|
||||
reinterpret_cast<HpkeSymmetricSuite*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<unsigned int*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure, SSL_EncodeEchConfigId(
|
||||
0, "name", 1, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1),
|
||||
reinterpret_cast<HpkeSymmetricSuite*>(1), 1,
|
||||
nullptr, reinterpret_cast<unsigned int*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig(nullptr, reinterpret_cast<uint32_t*>(1), 1,
|
||||
static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1), 0,
|
||||
reinterpret_cast<uint8_t*>(1),
|
||||
reinterpret_cast<uint32_t*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig("name", reinterpret_cast<uint32_t*>(1), 1,
|
||||
static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1), 1,
|
||||
nullptr, reinterpret_cast<uint32_t*>(1), 1));
|
||||
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_EncodeEchConfig("name", reinterpret_cast<uint32_t*>(1), 1,
|
||||
static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1), nullptr, 1));
|
||||
SSL_EncodeEchConfigId(0, "name", 1, static_cast<HpkeKemId>(1),
|
||||
reinterpret_cast<SECKEYPublicKey*>(1),
|
||||
reinterpret_cast<HpkeSymmetricSuite*>(1), 1,
|
||||
reinterpret_cast<uint8_t*>(1), nullptr, 1));
|
||||
}
|
||||
|
||||
TEST_P(TlsAgentEchTest, NoEarlyRetryConfigs) {
|
||||
|
@ -584,21 +583,45 @@ TEST_P(TlsAgentEchTest, EchConfigDuplicateExtensions) {
|
|||
ASSERT_FALSE(filter->captured());
|
||||
}
|
||||
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchFixedConfig) {
|
||||
ScopedSECKEYPublicKey pub;
|
||||
ScopedSECKEYPrivateKey priv;
|
||||
EnsureTlsSetup();
|
||||
ImportFixedEchKeypair(pub, priv);
|
||||
SetMutualEchConfigs(pub, priv);
|
||||
|
||||
client_->ExpectEch();
|
||||
server_->ExpectEch();
|
||||
Connect();
|
||||
}
|
||||
|
||||
// The next set of tests all use a fixed server key and a pre-built ClientHello.
|
||||
// This ClientHelo can be constructed using the above EchFixedConfig test,
|
||||
// modifying tls13_ConstructInnerExtensionsFromOuter as indicated. For this
|
||||
// small number of tests, these fixed values are easier to construct than
|
||||
// constructing ClientHello in the test that can be successfully decrypted.
|
||||
|
||||
// Test an encoded ClientHelloInner containing an extra extensionType
|
||||
// in outer_extensions, for which there is no corresponding (uncompressed)
|
||||
// extension in ClientHelloOuter.
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchOuterExtensionsReferencesMissing) {
|
||||
// Construct this by prepending 0xabcd to ssl_tls13_outer_extensions_xtn.
|
||||
std::string ch =
|
||||
"010001580303dfff91b5e1ba00f29d2338419b3abf125ee1051a942ae25163bbf609a1ea"
|
||||
"11920000061301130313020100012900000010000e00000b7075626c69632e6e616d65ff"
|
||||
"01000200030341a6813ccf3eefc2deb9c78f7627715ae343f5236e7224f454c723c93e0b"
|
||||
"d875000006130113031302010001d100000010000e00000b7075626c69632e6e616d65ff"
|
||||
"01000100000a00140012001d00170018001901000101010201030104003300260024001d"
|
||||
"0020d94c1590c261e9ea8ae55bc9581f397cc598115f8b70aec1b0236f4c8c555537002b"
|
||||
"00200573a70286658ad4bc166d8f5f237f035714ba5ae4e838c077677ccb6d619813002b"
|
||||
"0003020304000d0018001604030503060302030804080508060401050106010201002d00"
|
||||
"020101001c00024001fe09009b0001000308fde4163c5c6e8bb6002067a895efa2721c88"
|
||||
"63ecfa1bea1e520ae6f6cf938e3e37802688f7a83a871a04006aa693f053f87db87cf82a"
|
||||
"7caa20670d79b92ccda97893fdf99352fc766fb3dd5570948311dddb6d41214234fae585"
|
||||
"e354a048c072b3fb00a0a64e8e089e4a90152ee91a2c5b947c99d3dcebfb6334453b023d"
|
||||
"4d725010996a290a0552e4b238ec91c21440adc0d51a4435";
|
||||
"020101001c00024001001500aa0000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000fe0a0095000100034d00209c68779a77e4bac0e9f39c2974b1900de044ae1510bf"
|
||||
"d34fb5120a2a9d039607006c76c4571099733157eb8614ef2ad6049372e9fdf740f8ad4f"
|
||||
"d24723702c9104a38ecc366eea78b0285422b3f119fc057e2282433a74d8c56b2135c785"
|
||||
"bd5d01f89b2dbb42aa9a609eb1c6dd89252fa04cf8fbc4097e9c85da1e3eeebc188bbe16"
|
||||
"db1166f6df1a0c7c6e0dce71";
|
||||
ReplayChWithMalformedInner(ch, kTlsAlertIllegalParameter,
|
||||
SSL_ERROR_RX_MALFORMED_ECH_EXTENSION,
|
||||
SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
|
@ -606,17 +629,23 @@ TEST_F(TlsConnectStreamTls13Ech, EchOuterExtensionsReferencesMissing) {
|
|||
|
||||
// Drop supported_versions from CHInner, make sure we don't negotiate 1.2+ECH.
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchVersion12Inner) {
|
||||
// Construct this by removing ssl_tls13_supported_versions_xtn entirely.
|
||||
std::string ch =
|
||||
"0100015103038fbe6f75b0123116fa5c4eccf0cf26c17ab1ded5529307e419c036ac7e9c"
|
||||
"e8e30000061301130313020100012200000010000e00000b7075626c69632e6e616d65ff"
|
||||
"010002000303baf30ea25e5056b659a4d55233922c4ee261a04e6d84c8200713edca2f55"
|
||||
"d434000006130113031302010001d100000010000e00000b7075626c69632e6e616d65ff"
|
||||
"01000100000a00140012001d00170018001901000101010201030104003300260024001d"
|
||||
"002078d644583b4f056bec4d8ae9bddd383aed6eb7cdb3294f88b0e37a4f26a02549002b"
|
||||
"002081908a3cf3ed9ebf6d6b1f7082d77bb3bf8ff309c3c1255421720c4172548762002b"
|
||||
"0003020304000d0018001604030503060302030804080508060401050106010201002d00"
|
||||
"020101001c00024001fe0900940001000308fde4163c5c6e8bb600208958e66d1d4bbd46"
|
||||
"4792f392e119dbce91ee3e65067899b45c83855dae61e67a00637df038e7b35483786707"
|
||||
"dd1b25be5cd3dd07f1ca4b33a3595ddb959e5c0da3d2f0b3314417614968691700c05232"
|
||||
"07c729b34f3b5de62728b3cb6b45b00e6f94b204a9504d0e7e24c66f42aacc73591c86ef"
|
||||
"571e61cebd6ba671081150a2dae89e7493";
|
||||
"020101001c00024001001500b30000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000fe0a008c000100034d0020305bc263a664387b90a6975b2a"
|
||||
"3aa1e4358e80a8ca0841237035d2475628582d006352a2b49912a61543dfa045c1429582"
|
||||
"540c8c7019968867fde698eb37667f9aa9c23d02757492a4580fb027bbe4ba7615eea118"
|
||||
"ad3bf7f02a88f8372cfa01888e7be0c55616f846e902bbdfc7edf56994d6398f5a965d9e"
|
||||
"c4b1bc7afc580b28b0ac91d8";
|
||||
ReplayChWithMalformedInner(ch, kTlsAlertProtocolVersion,
|
||||
SSL_ERROR_UNSUPPORTED_VERSION,
|
||||
SSL_ERROR_PROTOCOL_VERSION_ALERT);
|
||||
|
@ -624,35 +653,48 @@ TEST_F(TlsConnectStreamTls13Ech, EchVersion12Inner) {
|
|||
|
||||
// Use CHInner supported_versions to negotiate 1.2.
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchVersion12InnerSupportedVersions) {
|
||||
// Construct this by changing ssl_tls13_supported_versions_xtn to write
|
||||
// TLS 1.2 instead of TLS 1.3.
|
||||
std::string ch =
|
||||
"01000158030378a601a3f12229e53e0b8d92c3599bf1782e8261d2ecaec9bbe595d4c901"
|
||||
"98770000061301130313020100012900000010000e00000b7075626c69632e6e616d65ff"
|
||||
"0100020003036c4a7f6f6b5479a5c1f769c7b04c082ba40b514522d193df855df8bea933"
|
||||
"b565000006130113031302010001d100000010000e00000b7075626c69632e6e616d65ff"
|
||||
"01000100000a00140012001d00170018001901000101010201030104003300260024001d"
|
||||
"00201c8017d6970f3a92ac1c9919c3a26788052f84599fb0c3cb7bd381304148724e002b"
|
||||
"0020ee721b8fe89260f8987d0d21b628db136c6155793fa63f4f546b244ee5357761002b"
|
||||
"0003020304000d0018001604030503060302030804080508060401050106010201002d00"
|
||||
"020101001c00024001fe09009b0001000308fde4163c5c6e8bb60020f7347d34f125e866"
|
||||
"76b1cdc43455c6c00918a3c8a961335e1b9aa864da2b5313006a21e6ad81533e90cea24e"
|
||||
"c2c3656f6b53114b4c63bf89462696f1c8ad4e1193d87062a5537edbe83c9b35c41e9763"
|
||||
"1d2333270854758ee02548afb7f2264f904474465415a5085024487f22b017208e250ca4"
|
||||
"7902d61d98fbd1cb8afc0a14dcd70a68343cf67c258758d9";
|
||||
"020101001c00024001001500ac0000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000fe0a0093000100034d00205de27fe39481bfb370ee8441f12e28296bc5c8fe"
|
||||
"b6a6198ddc6ab03b2d024638006a9e9f57c3f39c0ad1c3427549a77f301d01d718e09da4"
|
||||
"5497df178c95fd598bf0c9098d68dfba80a05eeeabc84dc0bb3225cee4a74688d520c632"
|
||||
"73612f98be847dea4f040a8d9b2b92bb4a44273d0cafafbfe1ee4ed69448bc243b4359c6"
|
||||
"e1eb3971e125fbfb016245fa";
|
||||
ReplayChWithMalformedInner(ch, kTlsAlertProtocolVersion,
|
||||
SSL_ERROR_UNSUPPORTED_VERSION,
|
||||
SSL_ERROR_PROTOCOL_VERSION_ALERT);
|
||||
}
|
||||
|
||||
// Replay a CH for which CHInner lacks the required ech_is_inner extension.
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchInnerMissingEmptyEch) {
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchInnerMissing) {
|
||||
// Construct by omitting ssl_tls13_ech_is_inner_xtn.
|
||||
std::string ch =
|
||||
"010001540303033b3284790ada882445bfb38b8af3509659033c931e6ae97febbaa62b19"
|
||||
"b4ac0000061301130313020100012500000010000e00000b7075626c69632e6e616d65ff"
|
||||
"010002000303912d293136b843248ffeecdde6ef0d5bc5d0adb4d356b985c2fcec8fe2b0"
|
||||
"8f5d000006130113031302010001d100000010000e00000b7075626c69632e6e616d65ff"
|
||||
"01000100000a00140012001d00170018001901000101010201030104003300260024001d"
|
||||
"00209d1ed410ccb05ce9e424f52b1be3599bcc1efb0913ae14a24d9a69cbfbc39744002b"
|
||||
"00209222e6b0c672fd1e564fbca5889155e9126e3b006a8ff77ff61898dd56a08429002b"
|
||||
"0003020304000d0018001604030503060302030804080508060401050106010201002d00"
|
||||
"020101001c00024001fe0900970001000308fde4163c5c6e8bb600206321bdc543a23d47"
|
||||
"7a7104ba69177cb722927c6c485117df4a077b8e82167f0b0066103d9aac7e5fc4ef990b"
|
||||
"2ce38593589f7f6ba043847d7db6c9136adb811f63b956d56e6ca8cbe6864e3fc43a3bc5"
|
||||
"94a332d4d63833e411c89ef14af63b5cd18c7adee99ffd1ad3112449ea18d6650bbaca66"
|
||||
"528f7e4146fafbf338c27cf89b145a55022b26a3";
|
||||
"020101001c00024001001500b00000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000fe0a008f000100034d0020e1bc83c066a251621c4b055779789a2c"
|
||||
"6ac4b9a3850366b2ea0d32a8e041181c0066a4e9cc6912b8bc6c1b54a2c6c40428ab01a3"
|
||||
"0e4621ec65320df2beff846a606618429c108fdfe24a6fad5053f53fb36082bf7d80d6f4"
|
||||
"73131a3d6c04e182595606070ac4e0be078ada56456c02d37a2fee7cb17accd273cbd810"
|
||||
"30ee0dbe139e51ba1d2a471f";
|
||||
ReplayChWithMalformedInner(ch, kTlsAlertIllegalParameter,
|
||||
SSL_ERROR_MISSING_ECH_EXTENSION,
|
||||
SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
|
@ -661,17 +703,24 @@ TEST_F(TlsConnectStreamTls13Ech, EchInnerMissingEmptyEch) {
|
|||
// Replay a CH for which CHInner contains both an ECH and ech_is_inner
|
||||
// extension.
|
||||
TEST_F(TlsConnectStreamTls13Ech, InnerWithEchAndEchIsInner) {
|
||||
// Construct by appending an empty ssl_tls13_encrypted_client_hello_xtn to
|
||||
// CHInner.
|
||||
std::string ch =
|
||||
"0100015c030383fb49c98b62bcdf04cbbae418dd684f8f9512f40fca6861ba40555269a9"
|
||||
"789f0000061301130313020100012d00000010000e00000b7075626c69632e6e616d65ff"
|
||||
"010002000303b690bc4090ecfd7ad167de639b1d1ea7682588ffefae1164179d370f6cd3"
|
||||
"0864000006130113031302010001d100000010000e00000b7075626c69632e6e616d65ff"
|
||||
"01000100000a00140012001d00170018001901000101010201030104003300260024001d"
|
||||
"00201e3d35a6755b7dddf7e481359429e9677baaa8dd99569c2bf0b0f7ea56e68b12002b"
|
||||
"00200c3c15b0e9884d5f593634a168b70a62ae18c8d69a68f8e29c826fbabcd99b22002b"
|
||||
"0003020304000d0018001604030503060302030804080508060401050106010201002d00"
|
||||
"020101001c00024001fe09009f0001000308fde4163c5c6e8bb6002090110b89c1ba6618"
|
||||
"942ea7aae8c472c22e97f10bef7dd490bee50cc108082b48006eed016fa2b3e3419cf5ef"
|
||||
"9b41ab9ecffa84a4b60e2f4cc710cf31c739d1f6f88b48207aaf7ccabdd744a25a8f2a38"
|
||||
"029d1b133e9d990681cf08c07a255d9242b3a002bc0865935cbb609b2b1996fab0626cb0"
|
||||
"2ece6544bbde0d3218333ffd95c383a41854b76b1a254bb346a2702b";
|
||||
"020101001c00024001001500a80000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00fe0a0097000100034d0020d46cc9042eff6efee046a5ff653d1b6a60cfd5786afef5ce"
|
||||
"43300bc515ef5f09006ea6bf626854596df74b2d8f81a479a6d2fef13295a81e0571008a"
|
||||
"12fc92f82170fdb899cd22ebadc33a3147c2801619f7621ffe8684c96918443e3fbe9b17"
|
||||
"34fbf678ba0b2abad7ab6b018bccc1034b9537a5d399fdb9a5ccb92360bde4a94a2f2509"
|
||||
"0e7313dd9254eae3603e1fee";
|
||||
ReplayChWithMalformedInner(ch, kTlsAlertIllegalParameter,
|
||||
SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
|
||||
SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
|
@ -701,13 +750,13 @@ TEST_F(TlsConnectStreamTls13Ech, EchConfigsTrialDecrypt) {
|
|||
ImportFixedEchKeypair(pub, priv);
|
||||
|
||||
const std::string two_configs_str =
|
||||
"007EFE09003B000B7075626C69632E6E616D650020111111111111111111111111111111"
|
||||
"1111111111111111111111111111111111002000040001000100640000fe09003B000B70"
|
||||
"75626C69632E6E616D6500208756E2580C07C1D2FFCB662F5FADC6D6FF13DA85ABD7ADFE"
|
||||
"CF984AAA102C1269002000040001000100640000";
|
||||
"0080FE0A003C000020002011111111111111111111111111111111111111111111111111"
|
||||
"111111111111110004000100010064000B7075626C69632E6E616D650000FE0A003C0000"
|
||||
"2000208756E2580C07C1D2FFCB662F5FADC6D6FF13DA85ABD7ADFECF984AAA102C126900"
|
||||
"04000100010064000B7075626C69632E6E616D650000";
|
||||
const std::string second_config_str =
|
||||
"003FFE09003B000B7075626C69632E6E616D6500208756E2580C07C1D2FFCB662F5FADC6"
|
||||
"D6FF13DA85ABD7ADFECF984AAA102C1269002000040001000100640000";
|
||||
"0040FE0A003C00002000208756E2580C07C1D2FFCB662F5FADC6D6FF13DA85ABD7ADFECF"
|
||||
"984AAA102C12690004000100010064000B7075626C69632E6E616D650000";
|
||||
std::vector<uint8_t> two_configs = hex_string_to_bytes(two_configs_str);
|
||||
std::vector<uint8_t> second_config = hex_string_to_bytes(second_config_str);
|
||||
ASSERT_EQ(SECSuccess,
|
||||
|
@ -717,38 +766,11 @@ TEST_F(TlsConnectStreamTls13Ech, EchConfigsTrialDecrypt) {
|
|||
SSL_SetClientEchConfigs(client_->ssl_fd(), second_config.data(),
|
||||
second_config.size()));
|
||||
|
||||
ASSERT_EQ(SECSuccess, SSLInt_ZeroEchConfigIds(client_->ssl_fd()));
|
||||
ASSERT_EQ(SECSuccess, SSLInt_ZeroEchConfigIds(server_->ssl_fd()));
|
||||
client_->ExpectEch();
|
||||
server_->ExpectEch();
|
||||
Connect();
|
||||
}
|
||||
|
||||
// An empty config_id should prompt an alert. We don't support
|
||||
// Optional Configuration Identifiers.
|
||||
TEST_F(TlsConnectStreamTls13, EchRejectEmptyConfigId) {
|
||||
static const uint8_t junk[16] = {0};
|
||||
DataBuffer junk_buf(junk, sizeof(junk));
|
||||
DataBuffer ech_xtn;
|
||||
ech_xtn.Write(ech_xtn.len(), HpkeKdfHkdfSha256, 2);
|
||||
ech_xtn.Write(ech_xtn.len(), HpkeAeadAes128Gcm, 2);
|
||||
ech_xtn.Write(ech_xtn.len(), 0U, 1); // empty config_id
|
||||
ech_xtn.Write(ech_xtn.len(), junk_buf.len(), 2); // enc
|
||||
ech_xtn.Append(junk_buf);
|
||||
ech_xtn.Write(ech_xtn.len(), junk_buf.len(), 2); // payload
|
||||
ech_xtn.Append(junk_buf);
|
||||
|
||||
EnsureTlsSetup();
|
||||
EXPECT_EQ(SECSuccess, SSL_EnableTls13GreaseEch(client_->ssl_fd(),
|
||||
PR_FALSE)); // Don't GREASE
|
||||
MakeTlsFilter<TlsExtensionAppender>(client_, kTlsHandshakeClientHello,
|
||||
ssl_tls13_encrypted_client_hello_xtn,
|
||||
ech_xtn);
|
||||
ConnectExpectAlert(server_, kTlsAlertDecodeError);
|
||||
client_->CheckErrorCode(SSL_ERROR_DECODE_ERROR_ALERT);
|
||||
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ECH_EXTENSION);
|
||||
}
|
||||
|
||||
TEST_F(TlsConnectStreamTls13Ech, EchAcceptBasic) {
|
||||
EnsureTlsSetup();
|
||||
SetupEch(client_, server_);
|
||||
|
@ -1755,25 +1777,5 @@ TEST_F(TlsConnectStreamTls13, EchBackendAcceptance) {
|
|||
INSTANTIATE_TEST_SUITE_P(EchAgentTest, TlsAgentEchTest,
|
||||
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
|
||||
TlsConnectTestBase::kTlsV13));
|
||||
#else
|
||||
|
||||
TEST_P(TlsAgentEchTest, NoEchWithoutHpke) {
|
||||
EnsureInit();
|
||||
uint8_t non_null[1];
|
||||
SECKEYPublicKey pub;
|
||||
SECKEYPrivateKey priv;
|
||||
ASSERT_EQ(SECFailure, SSL_SetClientEchConfigs(agent_->ssl_fd(), non_null,
|
||||
sizeof(non_null)));
|
||||
ASSERT_EQ(SSL_ERROR_FEATURE_DISABLED, PORT_GetError());
|
||||
|
||||
ASSERT_EQ(SECFailure, SSL_SetServerEchConfigs(agent_->ssl_fd(), &pub, &priv,
|
||||
non_null, sizeof(non_null)));
|
||||
ASSERT_EQ(SSL_ERROR_FEATURE_DISABLED, PORT_GetError());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(EchAgentTest, TlsAgentEchTest,
|
||||
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
|
||||
TlsConnectTestBase::kTlsV13));
|
||||
|
||||
#endif // NSS_ENABLE_DRAFT_HPKE
|
||||
} // namespace nss_test
|
||||
|
|
|
@ -299,8 +299,9 @@ ifdef USE_64
|
|||
ifeq ($(PPC_ABI),2)
|
||||
ASFILES += sha512-p8.s
|
||||
ifeq ($(OS_TEST),ppc64le)
|
||||
EXTRA_SRCS += chacha20poly1305-ppc.c
|
||||
ASFILES += chacha20-ppc64le.s
|
||||
DEFINES += -DPPC_GCM
|
||||
EXTRA_SRCS += chacha20poly1305-ppc.c ppc-gcm-wrap.c
|
||||
ASFILES += chacha20-ppc64le.s ppc-gcm.s
|
||||
endif # ppc64le
|
||||
endif
|
||||
endif # USE_64
|
||||
|
|
|
@ -284,6 +284,41 @@
|
|||
}]
|
||||
]
|
||||
},
|
||||
{
|
||||
'target_name': 'gcm-aes-ppc_lib',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'ppc-gcm.s',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports'
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'ppc-gcm-wrap-nodepend_c_lib',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'ppc-gcm-wrap.c',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'gcm-aes-ppc_lib',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'ppc-gcm-wrap_c_lib',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'ppc-gcm-wrap.c',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'gcm-aes-ppc_lib',
|
||||
],
|
||||
'defines!': [
|
||||
'FREEBL_NO_DEPEND',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'gcm-sha512-nodepend-ppc_c_lib',
|
||||
'type': 'static_library',
|
||||
|
@ -466,6 +501,7 @@
|
|||
'gcm-aes-ppc_c_lib',
|
||||
'gcm-sha512-ppc_c_lib',
|
||||
'chacha20-ppc_lib',
|
||||
'ppc-gcm-wrap_c_lib',
|
||||
],
|
||||
}],
|
||||
[ 'disable_altivec==1 and (target_arch=="ppc64" or target_arch=="ppc64le")', {
|
||||
|
@ -484,6 +520,7 @@
|
|||
'FREEBL_LOWHASH',
|
||||
'USE_HW_AES',
|
||||
'INTEL_GCM',
|
||||
'PPC_GCM',
|
||||
],
|
||||
'conditions': [
|
||||
[ 'target_arch=="x64"', {
|
||||
|
@ -535,10 +572,20 @@
|
|||
'gcm-aes-aarch64_c_lib',
|
||||
],
|
||||
}],
|
||||
[ 'disable_altivec==0 and (target_arch=="ppc64" or target_arch=="ppc64le")', {
|
||||
'dependencies': [
|
||||
'gcm-aes-ppc_c_lib',
|
||||
'gcm-sha512-nodepend-ppc_c_lib',
|
||||
[ 'disable_altivec==0', {
|
||||
'conditions': [
|
||||
[ 'target_arch=="ppc64"', {
|
||||
'dependencies': [
|
||||
'gcm-aes-ppc_c_lib',
|
||||
'gcm-sha512-nodepend-ppc_c_lib',
|
||||
],
|
||||
}, 'target_arch=="ppc64le"', {
|
||||
'dependencies': [
|
||||
'gcm-aes-ppc_c_lib',
|
||||
'gcm-sha512-nodepend-ppc_c_lib',
|
||||
'ppc-gcm-wrap-nodepend_c_lib',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
[ 'disable_altivec==1 and (target_arch=="ppc64" or target_arch=="ppc64le")', {
|
||||
|
@ -743,6 +790,13 @@
|
|||
'FREEBL_LOWHASH',
|
||||
'FREEBL_NO_DEPEND',
|
||||
],
|
||||
'conditions': [
|
||||
[ 'disable_altivec==0 and target_arch=="ppc64le"', {
|
||||
'defines': [
|
||||
'PPC_GCM',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
[ 'OS=="linux" or OS=="android"', {
|
||||
'conditions': [
|
||||
|
|
|
@ -0,0 +1,458 @@
|
|||
/* 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/. */
|
||||
/* Copyright(c) 2013, Intel Corp. */
|
||||
|
||||
/* Wrapper functions for PowerPC optimized implementation of AES-GCM */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "blapii.h"
|
||||
#include "blapit.h"
|
||||
#include "gcm.h"
|
||||
#include "ctr.h"
|
||||
#include "secerr.h"
|
||||
#include "prtypes.h"
|
||||
#include "pkcs11t.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ppc-gcm.h"
|
||||
#include "rijndael.h"
|
||||
|
||||
struct ppc_AES_GCMContextStr {
|
||||
unsigned char Htbl[8 * AES_BLOCK_SIZE];
|
||||
unsigned char X0[AES_BLOCK_SIZE];
|
||||
unsigned char T[AES_BLOCK_SIZE];
|
||||
unsigned char CTR[AES_BLOCK_SIZE];
|
||||
AESContext *aes_context;
|
||||
unsigned long tagBits;
|
||||
unsigned long Alen;
|
||||
unsigned long Mlen;
|
||||
freeblCipherFunc cipher;
|
||||
PRBool ctr_context_init;
|
||||
gcmIVContext gcm_iv;
|
||||
};
|
||||
|
||||
SECStatus ppc_aes_gcmInitCounter(ppc_AES_GCMContext *gcm,
|
||||
const unsigned char *iv,
|
||||
unsigned long ivLen, unsigned long tagBits,
|
||||
const unsigned char *aad, unsigned long aadLen);
|
||||
|
||||
ppc_AES_GCMContext *
|
||||
ppc_AES_GCM_CreateContext(void *context,
|
||||
freeblCipherFunc cipher,
|
||||
const unsigned char *params)
|
||||
{
|
||||
ppc_AES_GCMContext *gcm = NULL;
|
||||
AESContext *aes = (AESContext *)context;
|
||||
const CK_NSS_GCM_PARAMS *gcmParams = (const CK_NSS_GCM_PARAMS *)params;
|
||||
SECStatus rv;
|
||||
|
||||
gcm = PORT_ZNew(ppc_AES_GCMContext);
|
||||
if (gcm == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize context fields */
|
||||
gcm->aes_context = aes;
|
||||
gcm->cipher = cipher;
|
||||
gcm->Alen = 0;
|
||||
gcm->Mlen = 0;
|
||||
gcm->ctr_context_init = PR_FALSE;
|
||||
|
||||
/* first prepare H and its derivatives for ghash */
|
||||
ppc_aes_gcmINIT(gcm->Htbl, aes->k.expandedKey, aes->Nr);
|
||||
|
||||
gcm_InitIVContext(&gcm->gcm_iv);
|
||||
|
||||
/* if gcmParams is NULL, then we are creating an PKCS #11 MESSAGE
|
||||
* style context, in which we initialize the key once, then do separate
|
||||
* iv/aad's for each message. If we are doing that kind of operation,
|
||||
* we've finished with init here. We'll init the Counter in each AEAD
|
||||
* call */
|
||||
if (gcmParams == NULL) {
|
||||
return gcm;
|
||||
}
|
||||
|
||||
rv = ppc_aes_gcmInitCounter(gcm, gcmParams->pIv,
|
||||
gcmParams->ulIvLen, gcmParams->ulTagBits,
|
||||
gcmParams->pAAD, gcmParams->ulAADLen);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_Free(gcm);
|
||||
return NULL;
|
||||
}
|
||||
gcm->ctr_context_init = PR_TRUE;
|
||||
|
||||
return gcm;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ppc_aes_gcmInitCounter(ppc_AES_GCMContext *gcm,
|
||||
const unsigned char *iv, unsigned long ivLen,
|
||||
unsigned long tagBits,
|
||||
const unsigned char *aad, unsigned long aadLen)
|
||||
{
|
||||
unsigned int j;
|
||||
SECStatus rv;
|
||||
|
||||
if (ivLen == 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (tagBits != 128 && tagBits != 120 && tagBits != 112 &&
|
||||
tagBits != 104 && tagBits != 96 && tagBits != 64 &&
|
||||
tagBits != 32) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
gcm->tagBits = tagBits;
|
||||
|
||||
/* reset the aad and message length counters */
|
||||
gcm->Alen = 0;
|
||||
gcm->Mlen = 0;
|
||||
|
||||
/* Initial TAG value is zero */
|
||||
PORT_Memset(gcm->T, 0, AES_BLOCK_SIZE);
|
||||
PORT_Memset(gcm->X0, 0, AES_BLOCK_SIZE);
|
||||
|
||||
/* Init the counter */
|
||||
if (ivLen == 12) {
|
||||
PORT_Memcpy(gcm->CTR, iv, AES_BLOCK_SIZE - 4);
|
||||
gcm->CTR[12] = 0;
|
||||
gcm->CTR[13] = 0;
|
||||
gcm->CTR[14] = 0;
|
||||
gcm->CTR[15] = 1;
|
||||
} else {
|
||||
/* If IV size is not 96 bits, then the initial counter value is GHASH
|
||||
* of the IV */
|
||||
ppc_aes_gcmHASH(gcm->Htbl, iv, ivLen, gcm->T);
|
||||
|
||||
ppc_aes_gcmTAG(
|
||||
gcm->Htbl,
|
||||
gcm->T,
|
||||
ivLen,
|
||||
0,
|
||||
gcm->X0,
|
||||
gcm->CTR);
|
||||
|
||||
/* TAG should be zero again */
|
||||
PORT_Memset(gcm->T, 0, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/* Encrypt the initial counter, will be used to encrypt the GHASH value,
|
||||
* in the end */
|
||||
rv = (*gcm->cipher)(gcm->aes_context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR,
|
||||
AES_BLOCK_SIZE, AES_BLOCK_SIZE);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Promote the counter by 1 */
|
||||
gcm->CTR[14] += !(++gcm->CTR[15]);
|
||||
gcm->CTR[13] += !(gcm->CTR[15]) && !(gcm->CTR[14]);
|
||||
gcm->CTR[12] += !(gcm->CTR[15]) && !(gcm->CTR[13]) && !(gcm->CTR[12]);
|
||||
|
||||
/* Now hash AAD - it would actually make sense to seperate the context
|
||||
* creation from the AAD, because that would allow to reuse the H, which
|
||||
* only changes when the AES key changes, and not every package, like the
|
||||
* IV and AAD */
|
||||
ppc_aes_gcmHASH(gcm->Htbl, aad, aadLen, gcm->T);
|
||||
gcm->Alen += aadLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit)
|
||||
{
|
||||
PORT_Memset(gcm, 0, sizeof(ppc_AES_GCMContext));
|
||||
if (freeit) {
|
||||
PORT_Free(gcm);
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ppc_AES_GCM_EncryptUpdate(ppc_AES_GCMContext *gcm,
|
||||
unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
unsigned int blocksize)
|
||||
{
|
||||
unsigned int tagBytes;
|
||||
unsigned char T[AES_BLOCK_SIZE];
|
||||
unsigned int j;
|
||||
|
||||
// GCM has a 16 octet block, with a 32-bit block counter
|
||||
// Limit in accordance with SP800-38D
|
||||
if (sizeof(inlen) > 4 &&
|
||||
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (!gcm->ctr_context_init) {
|
||||
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
|
||||
if (UINT_MAX - inlen < tagBytes) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxout < inlen + tagBytes) {
|
||||
*outlen = inlen + tagBytes;
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
ppc_aes_gcmCRYPT(
|
||||
inbuf,
|
||||
outbuf,
|
||||
inlen,
|
||||
gcm->CTR,
|
||||
gcm->aes_context->k.expandedKey,
|
||||
gcm->aes_context->Nr);
|
||||
ppc_aes_gcmHASH(
|
||||
gcm->Htbl,
|
||||
outbuf,
|
||||
inlen,
|
||||
gcm->T);
|
||||
|
||||
gcm->Mlen += inlen;
|
||||
|
||||
ppc_aes_gcmTAG(
|
||||
gcm->Htbl,
|
||||
gcm->T,
|
||||
gcm->Mlen,
|
||||
gcm->Alen,
|
||||
gcm->X0,
|
||||
T);
|
||||
|
||||
*outlen = inlen + tagBytes;
|
||||
|
||||
for (j = 0; j < tagBytes; j++) {
|
||||
outbuf[inlen + j] = T[j];
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ppc_AES_GCM_DecryptUpdate(ppc_AES_GCMContext *gcm,
|
||||
unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
unsigned int blocksize)
|
||||
{
|
||||
unsigned int tagBytes;
|
||||
unsigned char T[AES_BLOCK_SIZE];
|
||||
const unsigned char *intag;
|
||||
|
||||
if (!gcm->ctr_context_init) {
|
||||
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
|
||||
|
||||
/* get the authentication block */
|
||||
if (inlen < tagBytes) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
inlen -= tagBytes;
|
||||
intag = inbuf + inlen;
|
||||
|
||||
// GCM has a 16 octet block, with a 32-bit block counter
|
||||
// Limit in accordance with SP800-38D
|
||||
if (sizeof(inlen) > 4 &&
|
||||
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (maxout < inlen) {
|
||||
*outlen = inlen;
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
ppc_aes_gcmHASH(
|
||||
gcm->Htbl,
|
||||
inbuf,
|
||||
inlen,
|
||||
gcm->T);
|
||||
ppc_aes_gcmCRYPT(
|
||||
inbuf,
|
||||
outbuf,
|
||||
inlen,
|
||||
gcm->CTR,
|
||||
gcm->aes_context->k.expandedKey,
|
||||
gcm->aes_context->Nr);
|
||||
|
||||
gcm->Mlen += inlen;
|
||||
ppc_aes_gcmTAG(
|
||||
gcm->Htbl,
|
||||
gcm->T,
|
||||
gcm->Mlen,
|
||||
gcm->Alen,
|
||||
gcm->X0,
|
||||
T);
|
||||
|
||||
if (NSS_SecureMemcmp(T, intag, tagBytes) != 0) {
|
||||
memset(outbuf, 0, inlen);
|
||||
*outlen = 0;
|
||||
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
return SECFailure;
|
||||
}
|
||||
*outlen = inlen;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ppc_AES_GCM_EncryptAEAD(ppc_AES_GCMContext *gcm,
|
||||
unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
void *params, unsigned int paramLen,
|
||||
const unsigned char *aad, unsigned int aadLen,
|
||||
unsigned int blocksize)
|
||||
{
|
||||
unsigned int tagBytes;
|
||||
unsigned char T[AES_BLOCK_SIZE];
|
||||
const CK_GCM_MESSAGE_PARAMS *gcmParams =
|
||||
(const CK_GCM_MESSAGE_PARAMS *)params;
|
||||
SECStatus rv;
|
||||
|
||||
// GCM has a 16 octet block, with a 32-bit block counter
|
||||
// Limit in accordance with SP800-38D
|
||||
if (sizeof(inlen) > 4 &&
|
||||
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
/* paramLen comes all the way from the application layer, make sure
|
||||
* it's correct */
|
||||
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* if we were initialized with the C_EncryptInit, we shouldn't be in this
|
||||
* function */
|
||||
if (gcm->ctr_context_init) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (maxout < inlen) {
|
||||
*outlen = inlen;
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = gcm_GenerateIV(&gcm->gcm_iv, gcmParams->pIv, gcmParams->ulIvLen,
|
||||
gcmParams->ulIvFixedBits, gcmParams->ivGenerator);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ppc_aes_gcmInitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
|
||||
gcmParams->ulTagBits, aad, aadLen);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
|
||||
|
||||
ppc_aes_gcmCRYPT(inbuf, outbuf, inlen, gcm->CTR, gcm->aes_context->k.expandedKey,
|
||||
gcm->aes_context->Nr);
|
||||
ppc_aes_gcmHASH(gcm->Htbl, outbuf, inlen, gcm->T);
|
||||
|
||||
gcm->Mlen += inlen;
|
||||
|
||||
ppc_aes_gcmTAG(gcm->Htbl, gcm->T, gcm->Mlen, gcm->Alen, gcm->X0, T);
|
||||
|
||||
*outlen = inlen;
|
||||
PORT_Memcpy(gcmParams->pTag, T, tagBytes);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ppc_AES_GCM_DecryptAEAD(ppc_AES_GCMContext *gcm,
|
||||
unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
void *params, unsigned int paramLen,
|
||||
const unsigned char *aad, unsigned int aadLen,
|
||||
unsigned int blocksize)
|
||||
{
|
||||
unsigned int tagBytes;
|
||||
unsigned char T[AES_BLOCK_SIZE];
|
||||
const unsigned char *intag;
|
||||
const CK_GCM_MESSAGE_PARAMS *gcmParams =
|
||||
(const CK_GCM_MESSAGE_PARAMS *)params;
|
||||
SECStatus rv;
|
||||
|
||||
/* paramLen comes all the way from the application layer, make sure
|
||||
* it's correct */
|
||||
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* if we were initialized with the C_DecryptInit, we shouldn't be in this
|
||||
* function */
|
||||
if (gcm->ctr_context_init) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
// GCM has a 16 octet block, with a 32-bit block counter
|
||||
// Limit in accordance with SP800-38D
|
||||
if (sizeof(inlen) > 4 &&
|
||||
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (maxout < inlen) {
|
||||
*outlen = inlen;
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ppc_aes_gcmInitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
|
||||
gcmParams->ulTagBits, aad, aadLen);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
|
||||
intag = gcmParams->pTag;
|
||||
PORT_Assert(tagBytes != 0);
|
||||
|
||||
ppc_aes_gcmHASH(gcm->Htbl, inbuf, inlen, gcm->T);
|
||||
ppc_aes_gcmCRYPT(inbuf, outbuf, inlen, gcm->CTR, gcm->aes_context->k.expandedKey,
|
||||
gcm->aes_context->Nr);
|
||||
|
||||
gcm->Mlen += inlen;
|
||||
ppc_aes_gcmTAG(gcm->Htbl, gcm->T, gcm->Mlen, gcm->Alen, gcm->X0, T);
|
||||
|
||||
if (NSS_SecureMemcmp(T, intag, tagBytes) != 0) {
|
||||
memset(outbuf, 0, inlen);
|
||||
*outlen = 0;
|
||||
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
return SECFailure;
|
||||
}
|
||||
*outlen = inlen;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/******************************************************************************/
|
||||
/* LICENSE: */
|
||||
/* This submission to NSS is to be made available under the terms of the */
|
||||
/* Mozilla Public License, v. 2.0. You can obtain one at http: */
|
||||
/* //mozilla.org/MPL/2.0/. */
|
||||
/******************************************************************************/
|
||||
|
||||
#ifndef PPC_GCM_H
|
||||
#define PPC_GCM_H 1
|
||||
|
||||
#include "blapii.h"
|
||||
|
||||
typedef struct ppc_AES_GCMContextStr ppc_AES_GCMContext;
|
||||
|
||||
ppc_AES_GCMContext *ppc_AES_GCM_CreateContext(void *context, freeblCipherFunc cipher,
|
||||
const unsigned char *params);
|
||||
|
||||
void ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit);
|
||||
|
||||
SECStatus ppc_AES_GCM_EncryptUpdate(ppc_AES_GCMContext *gcm, unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
unsigned int blocksize);
|
||||
|
||||
SECStatus ppc_AES_GCM_DecryptUpdate(ppc_AES_GCMContext *gcm, unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
unsigned int blocksize);
|
||||
SECStatus ppc_AES_GCM_EncryptAEAD(ppc_AES_GCMContext *gcm,
|
||||
unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
void *params, unsigned int paramLen,
|
||||
const unsigned char *aad, unsigned int aadLen,
|
||||
unsigned int blocksize);
|
||||
SECStatus ppc_AES_GCM_DecryptAEAD(ppc_AES_GCMContext *gcm,
|
||||
unsigned char *outbuf,
|
||||
unsigned int *outlen, unsigned int maxout,
|
||||
const unsigned char *inbuf, unsigned int inlen,
|
||||
void *params, unsigned int paramLen,
|
||||
const unsigned char *aad, unsigned int aadLen,
|
||||
unsigned int blocksize);
|
||||
|
||||
/* Prototypes of the functions defined in the assembler file. */
|
||||
|
||||
/* Prepares the constants used in the aggregated reduction method */
|
||||
void ppc_aes_gcmINIT(unsigned char Htbl[8 * 16],
|
||||
PRUint32 *KS,
|
||||
int NR);
|
||||
|
||||
/* Produces the final GHASH value */
|
||||
void ppc_aes_gcmTAG(unsigned char Htbl[8 * 16],
|
||||
unsigned char *Tp,
|
||||
unsigned long Mlen,
|
||||
unsigned long Alen,
|
||||
unsigned char *X0,
|
||||
unsigned char *TAG);
|
||||
|
||||
/* Hashes the Additional Authenticated Data, should be used before enc/dec.
|
||||
Operates on any length of data. Partial block is padded internally. */
|
||||
void ppc_aes_gcmHASH(unsigned char Htbl[8 * 16],
|
||||
const unsigned char *AAD,
|
||||
unsigned long Alen,
|
||||
unsigned char *Tp);
|
||||
|
||||
/* Crypt only, used in combination with ppc_aes_gcmAAD().
|
||||
Operates on any length of data, however partial block should only be encrypted
|
||||
at the last call, otherwise the result will be incorrect. */
|
||||
void ppc_aes_gcmCRYPT(const unsigned char *PT,
|
||||
unsigned char *CT,
|
||||
unsigned long len,
|
||||
unsigned char *CTRP,
|
||||
PRUint32 *KS,
|
||||
int NR);
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -25,6 +25,10 @@
|
|||
#undef USE_HW_AES
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#include "ppc-crypto.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_HW_AES
|
||||
#ifdef NSS_X86_OR_X64
|
||||
#include "intel-aes.h"
|
||||
|
@ -35,6 +39,9 @@
|
|||
#ifdef INTEL_GCM
|
||||
#include "intel-gcm.h"
|
||||
#endif /* INTEL_GCM */
|
||||
#if defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
|
||||
#include "ppc-gcm.h"
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
void rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
|
||||
|
@ -1020,6 +1027,16 @@ AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
|
|||
cx->destroy = (freeblDestroyFunc)intel_AES_GCM_DestroyContext;
|
||||
cx->isBlock = PR_FALSE;
|
||||
} else
|
||||
#elif defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
|
||||
if (ppc_crypto_support() && (keysize % 8) == 0) {
|
||||
cx->worker_cx = ppc_AES_GCM_CreateContext(cx, cx->worker, iv);
|
||||
cx->worker = (freeblCipherFunc)(encrypt ? ppc_AES_GCM_EncryptUpdate
|
||||
: ppc_AES_GCM_DecryptUpdate);
|
||||
cx->worker_aead = (freeblAeadFunc)(encrypt ? ppc_AES_GCM_EncryptAEAD
|
||||
: ppc_AES_GCM_DecryptAEAD);
|
||||
cx->destroy = (freeblDestroyFunc)ppc_AES_GCM_DestroyContext;
|
||||
cx->isBlock = PR_FALSE;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv);
|
||||
|
|
|
@ -1224,6 +1224,9 @@ PK11_HPKE_ImportContext;
|
|||
;+ global:
|
||||
PK11_CreateContextByPubKey;
|
||||
PK11_CreateContextByPrivKey;
|
||||
PK11_ExportEncryptedPrivKeyInfoV2;
|
||||
PK11_ExportEncryptedPrivateKeyInfoV2;
|
||||
HASH_GetHMACOidTagByHashOidTag;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
|
|
@ -1969,14 +1969,20 @@ PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
|
|||
return pki;
|
||||
}
|
||||
|
||||
/* V2 refers to PKCS #5 V2 here. If a PKCS #5 v1 or PKCS #12 pbe is passed
|
||||
* for pbeTag, then encTag and hashTag are ignored. If pbe is an encryption
|
||||
* algorithm, then PKCS #5 V2 is used with prfTag for the prf. If prfTag isn't
|
||||
* supplied prf will be SEC_OID_HMAC_SHA1 */
|
||||
SECKEYEncryptedPrivateKeyInfo *
|
||||
PK11_ExportEncryptedPrivKeyInfo(
|
||||
PK11_ExportEncryptedPrivKeyInfoV2(
|
||||
PK11SlotInfo *slot, /* optional, encrypt key in this slot */
|
||||
SECOidTag algTag, /* encrypt key with this algorithm */
|
||||
SECOidTag pbeAlg, /* PBE algorithm to encrypt the with key */
|
||||
SECOidTag encAlg, /* Encryption algorithm to Encrypt the key with */
|
||||
SECOidTag prfAlg, /* Hash algorithm for PRF */
|
||||
SECItem *pwitem, /* password for PBE encryption */
|
||||
SECKEYPrivateKey *pk, /* encrypt this private key */
|
||||
int iteration, /* interations for PBE alg */
|
||||
void *wincx) /* context for password callback ? */
|
||||
void *pwArg) /* context for password callback */
|
||||
{
|
||||
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
||||
PLArenaPool *arena = NULL;
|
||||
|
@ -1997,7 +2003,7 @@ PK11_ExportEncryptedPrivKeyInfo(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
algid = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, SEC_OID_UNKNOWN,
|
||||
algid = sec_pkcs5CreateAlgorithmID(pbeAlg, encAlg, prfAlg,
|
||||
&pbeAlgTag, 0, NULL, iteration);
|
||||
if (algid == NULL) {
|
||||
return NULL;
|
||||
|
@ -2026,7 +2032,7 @@ PK11_ExportEncryptedPrivKeyInfo(
|
|||
slot = pk->pkcs11Slot;
|
||||
}
|
||||
}
|
||||
key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, wincx);
|
||||
key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, pwArg);
|
||||
if (key == NULL) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
|
@ -2120,6 +2126,46 @@ loser:
|
|||
return epki;
|
||||
}
|
||||
|
||||
SECKEYEncryptedPrivateKeyInfo *
|
||||
PK11_ExportEncryptedPrivKeyInfo(
|
||||
PK11SlotInfo *slot, /* optional, encrypt key in this slot */
|
||||
SECOidTag algTag, /* PBE algorithm to encrypt the with key */
|
||||
SECItem *pwitem, /* password for PBE encryption */
|
||||
SECKEYPrivateKey *pk, /* encrypt this private key */
|
||||
int iteration, /* interations for PBE alg */
|
||||
void *pwArg) /* context for password callback */
|
||||
{
|
||||
return PK11_ExportEncryptedPrivKeyInfoV2(slot, algTag, SEC_OID_UNKNOWN,
|
||||
SEC_OID_UNKNOWN, pwitem, pk,
|
||||
iteration, pwArg);
|
||||
}
|
||||
|
||||
/* V2 refers to PKCS #5 V2 here. If a PKCS #5 v1 or PKCS #12 pbe is passed
|
||||
* for pbeTag, then encTag and hashTag are ignored. If pbe is an encryption
|
||||
* algorithm, then PKCS #5 V2 is used with prfTag for the prf. If prfTag isn't
|
||||
* supplied prf will be SEC_OID_HMAC_SHA1 */
|
||||
SECKEYEncryptedPrivateKeyInfo *
|
||||
PK11_ExportEncryptedPrivateKeyInfoV2(
|
||||
PK11SlotInfo *slot, /* optional, encrypt key in this slot */
|
||||
SECOidTag pbeAlg, /* PBE algorithm to encrypt the with key */
|
||||
SECOidTag encAlg, /* Encryption algorithm to Encrypt the key with */
|
||||
SECOidTag prfAlg, /* HMAC algorithm for PRF*/
|
||||
SECItem *pwitem, /* password for PBE encryption */
|
||||
CERTCertificate *cert, /* wrap priv key for this user cert */
|
||||
int iteration, /* interations for PBE alg */
|
||||
void *pwArg) /* context for password callback */
|
||||
{
|
||||
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
||||
SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, pwArg);
|
||||
if (pk != NULL) {
|
||||
epki = PK11_ExportEncryptedPrivKeyInfoV2(slot, pbeAlg, encAlg, prfAlg,
|
||||
pwitem, pk, iteration,
|
||||
pwArg);
|
||||
SECKEY_DestroyPrivateKey(pk);
|
||||
}
|
||||
return epki;
|
||||
}
|
||||
|
||||
SECKEYEncryptedPrivateKeyInfo *
|
||||
PK11_ExportEncryptedPrivateKeyInfo(
|
||||
PK11SlotInfo *slot, /* optional, encrypt key in this slot */
|
||||
|
@ -2127,16 +2173,11 @@ PK11_ExportEncryptedPrivateKeyInfo(
|
|||
SECItem *pwitem, /* password for PBE encryption */
|
||||
CERTCertificate *cert, /* wrap priv key for this user cert */
|
||||
int iteration, /* interations for PBE alg */
|
||||
void *wincx) /* context for password callback ? */
|
||||
void *pwArg) /* context for password callback */
|
||||
{
|
||||
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
||||
SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, wincx);
|
||||
if (pk != NULL) {
|
||||
epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk,
|
||||
iteration, wincx);
|
||||
SECKEY_DestroyPrivateKey(pk);
|
||||
}
|
||||
return epki;
|
||||
return PK11_ExportEncryptedPrivateKeyInfoV2(slot, algTag, SEC_OID_UNKNOWN,
|
||||
SEC_OID_UNKNOWN, pwitem, cert,
|
||||
iteration, pwArg);
|
||||
}
|
||||
|
||||
SECItem *
|
||||
|
|
|
@ -18,97 +18,9 @@
|
|||
#include "secmodti.h"
|
||||
#include "secutil.h"
|
||||
|
||||
#ifndef NSS_ENABLE_DRAFT_HPKE
|
||||
/* "Not Implemented" stubs to maintain the ABI. */
|
||||
SECStatus
|
||||
PK11_HPKE_ValidateParameters(HpkeKemId kemId, HpkeKdfId kdfId, HpkeAeadId aeadId)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
HpkeContext *
|
||||
PK11_HPKE_NewContext(HpkeKemId kemId, HpkeKdfId kdfId, HpkeAeadId aeadId,
|
||||
PK11SymKey *psk, const SECItem *pskId)
|
||||
{
|
||||
#define SERIALIZATION_VERSION 2
|
||||
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_Deserialize(const HpkeContext *cx, const PRUint8 *enc,
|
||||
unsigned int encLen, SECKEYPublicKey **outPubKey)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
void
|
||||
PK11_HPKE_DestroyContext(HpkeContext *cx, PRBool freeit)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
}
|
||||
const SECItem *
|
||||
PK11_HPKE_GetEncapPubKey(const HpkeContext *cx)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_ExportContext(const HpkeContext *cx, PK11SymKey *wrapKey, SECItem **serialized)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_ExportSecret(const HpkeContext *cx, const SECItem *info,
|
||||
unsigned int L, PK11SymKey **outKey)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
HpkeContext *
|
||||
PK11_HPKE_ImportContext(const SECItem *serialized, PK11SymKey *wrapKey)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_Open(HpkeContext *cx, const SECItem *aad, const SECItem *ct,
|
||||
SECItem **outPt)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_Seal(HpkeContext *cx, const SECItem *aad, const SECItem *pt, SECItem **outCt)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_Serialize(const SECKEYPublicKey *pk, PRUint8 *buf, unsigned int *len, unsigned int maxLen)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_SetupS(HpkeContext *cx, const SECKEYPublicKey *pkE, SECKEYPrivateKey *skE,
|
||||
SECKEYPublicKey *pkR, const SECItem *info)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
SECStatus
|
||||
PK11_HPKE_SetupR(HpkeContext *cx, const SECKEYPublicKey *pkR, SECKEYPrivateKey *skR,
|
||||
const SECItem *enc, const SECItem *info)
|
||||
{
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
#else
|
||||
#define SERIALIZATION_VERSION 1
|
||||
|
||||
static const char *DRAFT_LABEL = "HPKE-07";
|
||||
static const char *V1_LABEL = "HPKE-v1";
|
||||
static const char *EXP_LABEL = "exp";
|
||||
static const char *HPKE_LABEL = "HPKE";
|
||||
static const char *INFO_LABEL = "info_hash";
|
||||
|
@ -142,17 +54,18 @@ static const hpkeKemParams kemParams[] = {
|
|||
{ HpkeDhKemX25519Sha256, 32, 32, 32, SEC_OID_CURVE25519, CKM_SHA256 },
|
||||
};
|
||||
|
||||
#define MAX_WRAPPED_EXP_LEN 72 // Largest kdfParams->Nh + 8
|
||||
#define MAX_WRAPPED_EXP_LEN 72 // Largest kdfParams->Nh + 8
|
||||
static const hpkeKdfParams kdfParams[] = {
|
||||
/* KDF, Nh, mechanism */
|
||||
{ HpkeKdfHkdfSha256, SHA256_LENGTH, CKM_SHA256 },
|
||||
{ HpkeKdfHkdfSha384, SHA384_LENGTH, CKM_SHA384 },
|
||||
{ HpkeKdfHkdfSha512, SHA512_LENGTH, CKM_SHA512 },
|
||||
};
|
||||
#define MAX_WRAPPED_KEY_LEN 40 // Largest aeadParams->Nk + 8
|
||||
#define MAX_WRAPPED_KEY_LEN 40 // Largest aeadParams->Nk + 8
|
||||
static const hpkeAeadParams aeadParams[] = {
|
||||
/* AEAD, Nk, Nn, tagLen, mechanism */
|
||||
{ HpkeAeadAes128Gcm, 16, 12, 16, CKM_AES_GCM },
|
||||
{ HpkeAeadAes256Gcm, 32, 12, 16, CKM_AES_GCM },
|
||||
{ HpkeAeadChaCha20Poly1305, 32, 12, 16, CKM_CHACHA20_POLY1305 },
|
||||
};
|
||||
|
||||
|
@ -188,8 +101,10 @@ aeadId2Params(HpkeAeadId aeadId)
|
|||
switch (aeadId) {
|
||||
case HpkeAeadAes128Gcm:
|
||||
return &aeadParams[0];
|
||||
case HpkeAeadChaCha20Poly1305:
|
||||
case HpkeAeadAes256Gcm:
|
||||
return &aeadParams[1];
|
||||
case HpkeAeadChaCha20Poly1305:
|
||||
return &aeadParams[2];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -320,7 +235,6 @@ PK11_HPKE_DestroyContext(HpkeContext *cx, PRBool freeit)
|
|||
/* Export Format:
|
||||
struct {
|
||||
uint8 serilizationVersion;
|
||||
uint8 hpkeVersion;
|
||||
uint16 kemId;
|
||||
uint16 kdfId;
|
||||
uint16 aeadId;
|
||||
|
@ -332,7 +246,7 @@ PK11_HPKE_DestroyContext(HpkeContext *cx, PRBool freeit)
|
|||
opaque exporterSecret<1..2^16-1>;
|
||||
} HpkeSerializedContext
|
||||
*/
|
||||
#define EXPORTED_CTX_BASE_LEN 26 /* Fixed size plus 2B for each variable. */
|
||||
#define EXPORTED_CTX_BASE_LEN 25 /* Fixed size plus 2B for each variable. */
|
||||
#define REMAINING_BYTES(walker, buf) \
|
||||
buf->len - (walker - buf->data)
|
||||
SECStatus
|
||||
|
@ -388,7 +302,6 @@ PK11_HPKE_ExportContext(const HpkeContext *cx, PK11SymKey *wrapKey, SECItem **se
|
|||
|
||||
walker = &serializedCx->data[0];
|
||||
*(walker)++ = (PRUint8)SERIALIZATION_VERSION;
|
||||
*(walker)++ = (PRUint8)HPKE_DRAFT_VERSION;
|
||||
|
||||
walker = encodeNumber(cx->kemParams->id, walker, 2);
|
||||
walker = encodeNumber(cx->kdfParams->id, walker, 2);
|
||||
|
@ -451,8 +364,6 @@ PK11_HPKE_ImportContext(const SECItem *serialized, PK11SymKey *wrapKey)
|
|||
|
||||
tmp8 = *(walker++);
|
||||
CHECK_FAIL_ERR((tmp8 != SERIALIZATION_VERSION), SEC_ERROR_BAD_DATA);
|
||||
tmp8 = *(walker++);
|
||||
CHECK_FAIL_ERR((tmp8 != HPKE_DRAFT_VERSION), SEC_ERROR_INVALID_ALGORITHM);
|
||||
|
||||
walker = decodeNumber(&tmpn, walker, 2);
|
||||
kem = (HpkeKemId)tmpn;
|
||||
|
@ -745,7 +656,7 @@ pk11_hpke_LabeledExtractData(const HpkeContext *cx, SECItem *salt,
|
|||
sizeof(params) };
|
||||
PORT_Assert(cx && ikm && label && labelLen && out && suiteId);
|
||||
|
||||
labeledIkm = pk11_hpke_MakeExtractLabel(DRAFT_LABEL, strlen(DRAFT_LABEL), label, labelLen, suiteId, ikm);
|
||||
labeledIkm = pk11_hpke_MakeExtractLabel(V1_LABEL, strlen(V1_LABEL), label, labelLen, suiteId, ikm);
|
||||
CHECK_FAIL(!labeledIkm);
|
||||
params.bExtract = CK_TRUE;
|
||||
params.bExpand = CK_FALSE;
|
||||
|
@ -800,7 +711,7 @@ pk11_hpke_LabeledExtract(const HpkeContext *cx, PK11SymKey *salt,
|
|||
sizeof(params) };
|
||||
PORT_Assert(cx && ikm && label && labelLen && out && suiteId);
|
||||
|
||||
innerLabel = pk11_hpke_MakeExtractLabel(DRAFT_LABEL, strlen(DRAFT_LABEL), label, labelLen, suiteId, NULL);
|
||||
innerLabel = pk11_hpke_MakeExtractLabel(V1_LABEL, strlen(V1_LABEL), label, labelLen, suiteId, NULL);
|
||||
CHECK_FAIL(!innerLabel);
|
||||
labelData.pData = innerLabel->data;
|
||||
labelData.ulLen = innerLabel->len;
|
||||
|
@ -849,15 +760,15 @@ pk11_hpke_LabeledExpand(const HpkeContext *cx, PK11SymKey *prk, const SECItem *s
|
|||
|
||||
walker = encodeNumber(L, walker, 2);
|
||||
len = info ? info->len : 0;
|
||||
len += sizeof(encodedL) + strlen(DRAFT_LABEL) + suiteId->len + labelLen;
|
||||
len += sizeof(encodedL) + strlen(V1_LABEL) + suiteId->len + labelLen;
|
||||
labeledInfoItem = SECITEM_AllocItem(NULL, NULL, len);
|
||||
CHECK_FAIL(!labeledInfoItem);
|
||||
|
||||
walker = labeledInfoItem->data;
|
||||
PORT_Memcpy(walker, encodedL, sizeof(encodedL));
|
||||
walker += sizeof(encodedL);
|
||||
PORT_Memcpy(walker, DRAFT_LABEL, strlen(DRAFT_LABEL));
|
||||
walker += strlen(DRAFT_LABEL);
|
||||
PORT_Memcpy(walker, V1_LABEL, strlen(V1_LABEL));
|
||||
walker += strlen(V1_LABEL);
|
||||
PORT_Memcpy(walker, suiteId->data, suiteId->len);
|
||||
walker += suiteId->len;
|
||||
PORT_Memcpy(walker, label, labelLen);
|
||||
|
@ -1362,5 +1273,3 @@ CLEANUP:
|
|||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif // NSS_ENABLE_DRAFT_HPKE
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
#include "blapit.h"
|
||||
#include "seccomon.h"
|
||||
|
||||
#ifdef NSS_ENABLE_DRAFT_HPKE
|
||||
#define HPKE_DRAFT_VERSION 7
|
||||
|
||||
#define CLEANUP \
|
||||
PORT_Assert(rv == SECSuccess); \
|
||||
cleanup
|
||||
|
@ -35,14 +32,12 @@
|
|||
goto cleanup; \
|
||||
}
|
||||
|
||||
#endif /* NSS_ENABLE_DRAFT_HPKE */
|
||||
|
||||
typedef enum {
|
||||
HpkeModeBase = 0,
|
||||
HpkeModePsk = 1,
|
||||
} HpkeModeId;
|
||||
|
||||
/* https://tools.ietf.org/html/draft-irtf-cfrg-hpke-07#section-7.1 */
|
||||
/* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hpke-08#section-7.1 */
|
||||
typedef enum {
|
||||
HpkeDhKemX25519Sha256 = 0x20,
|
||||
} HpkeKemId;
|
||||
|
@ -55,6 +50,7 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
HpkeAeadAes128Gcm = 1,
|
||||
HpkeAeadAes256Gcm = 2,
|
||||
HpkeAeadChaCha20Poly1305 = 3,
|
||||
} HpkeAeadId;
|
||||
|
||||
|
|
|
@ -627,10 +627,20 @@ SECKEYPrivateKeyInfo *PK11_ExportPrivateKeyInfo(
|
|||
CERTCertificate *cert, void *wincx);
|
||||
SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivKeyInfo(
|
||||
PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem,
|
||||
SECKEYPrivateKey *pk, int iteration, void *wincx);
|
||||
SECKEYPrivateKey *pk, int iteration, void *pwArg);
|
||||
SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivateKeyInfo(
|
||||
PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem,
|
||||
CERTCertificate *cert, int iteration, void *wincx);
|
||||
CERTCertificate *cert, int iteration, void *pwArg);
|
||||
/* V2 refers to PKCS #5 V2 here. If a PKCS #5 v1 or PKCS #12 pbe is passed
|
||||
* for pbeTag, then encTag and hashTag are ignored. If pbe is an encryption
|
||||
* algorithm, then PKCS #5 V2 is used with prfTag for the prf. If prfTag isn't
|
||||
* supplied prf will be SEC_OID_HMAC_SHA1 */
|
||||
SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivKeyInfoV2(
|
||||
PK11SlotInfo *slot, SECOidTag pbeTag, SECOidTag encTag, SECOidTag prfTag,
|
||||
SECItem *pwitem, SECKEYPrivateKey *pk, int iteration, void *pwArg);
|
||||
SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivateKeyInfoV2(
|
||||
PK11SlotInfo *slot, SECOidTag pbeTag, SECOidTag encTag, SECOidTag prfTag,
|
||||
SECItem *pwitem, CERTCertificate *cert, int iteration, void *pwArg);
|
||||
SECKEYPrivateKey *PK11_FindKeyByDERCert(PK11SlotInfo *slot,
|
||||
CERTCertificate *cert, void *wincx);
|
||||
SECKEYPublicKey *PK11_MakeKEAPubKey(unsigned char *data, int length);
|
||||
|
@ -728,14 +738,8 @@ CK_BBOOL PK11_HasAttributeSet(PK11SlotInfo *slot,
|
|||
PRBool haslock /* must be set to PR_FALSE */);
|
||||
|
||||
/**********************************************************************
|
||||
* Hybrid Public Key Encryption (draft-07)
|
||||
* Hybrid Public Key Encryption
|
||||
**********************************************************************/
|
||||
/*
|
||||
* NOTE: All HPKE functions will fail with SEC_ERROR_INVALID_ALGORITHM
|
||||
* unless NSS is compiled with NSS_ENABLE_DRAFT_HPKE while spec (and
|
||||
* implementation) is in draft. The eventual RFC number is an input to
|
||||
* the key schedule, so applications opting into this MUST be prepared for
|
||||
* outputs to change when the implementation is updated or finalized. */
|
||||
|
||||
/* Some of the various HPKE arguments would ideally be const, but the
|
||||
* underlying PK11 functions take them as non-const. To avoid lying to
|
||||
|
|
|
@ -1353,32 +1353,10 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
|
|||
iteration);
|
||||
|
||||
algtag = SECOID_GetAlgorithmTag(&p12dcx->macData.safeMac.digestAlgorithm);
|
||||
switch (algtag) {
|
||||
case SEC_OID_SHA1:
|
||||
integrityMech = CKM_NSS_PBE_SHA1_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_MD5:
|
||||
integrityMech = CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_MD2:
|
||||
integrityMech = CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA224:
|
||||
integrityMech = CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA256:
|
||||
integrityMech = CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA384:
|
||||
integrityMech = CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA512:
|
||||
integrityMech = CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN;
|
||||
break;
|
||||
default:
|
||||
goto loser;
|
||||
integrityMech = sec_pkcs12_algtag_to_keygen_mech(algtag);
|
||||
if (integrityMech == CKM_INVALID_MECHANISM) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
symKey = PK11_KeyGen(NULL, integrityMech, params, 0, NULL);
|
||||
PK11_DestroyPBEParams(params);
|
||||
params = NULL;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "secpkcs7.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
#include "sechash.h"
|
||||
#include "pk11func.h"
|
||||
#include "p12plcy.h"
|
||||
#include "p12local.h"
|
||||
|
@ -379,11 +380,18 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt,
|
|||
safeInfo->itemCount = 0;
|
||||
|
||||
/* create the encrypted safe */
|
||||
if (!SEC_PKCS5IsAlgorithmPBEAlgTag(privAlg) &&
|
||||
PK11_AlgtagToMechanism(privAlg) == CKM_AES_CBC) {
|
||||
if (!SEC_PKCS5IsAlgorithmPBEAlgTag(privAlg)) {
|
||||
SECOidTag prfAlg = SEC_OID_UNKNOWN;
|
||||
/* if we have password integrity set, use that to set the integrity
|
||||
* hash algorithm to set our password PRF. If we haven't set it, just
|
||||
* let the low level code pick it */
|
||||
if (p12ctxt->integrityEnabled && p12ctxt->pwdIntegrity) {
|
||||
prfAlg = HASH_GetHMACOidTagByHashOidTag(
|
||||
p12ctxt->integrityInfo.pwdInfo.algorithm);
|
||||
}
|
||||
safeInfo->cinfo = SEC_PKCS7CreateEncryptedDataWithPBEV2(SEC_OID_PKCS5_PBES2,
|
||||
privAlg,
|
||||
SEC_OID_UNKNOWN,
|
||||
prfAlg,
|
||||
0,
|
||||
p12ctxt->pwfn,
|
||||
p12ctxt->pwfnarg);
|
||||
|
@ -1213,6 +1221,7 @@ SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *sa
|
|||
/* extract the key encrypted */
|
||||
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
||||
PK11SlotInfo *slot = NULL;
|
||||
SECOidTag prfAlg = SEC_OID_UNKNOWN;
|
||||
|
||||
if (!sec_pkcs12_encode_password(p12ctxt->arena, &uniPwitem, algorithm,
|
||||
pwitem)) {
|
||||
|
@ -1220,6 +1229,14 @@ SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *sa
|
|||
goto loser;
|
||||
}
|
||||
|
||||
/* if we have password integrity set, use that to set the integrity
|
||||
* hash algorithm to set our password PRF. If we haven't set it, just
|
||||
* let the low level code pick it */
|
||||
if (p12ctxt->integrityEnabled && p12ctxt->pwdIntegrity) {
|
||||
prfAlg = HASH_GetHMACOidTagByHashOidTag(
|
||||
p12ctxt->integrityInfo.pwdInfo.algorithm);
|
||||
}
|
||||
|
||||
/* we want to make sure to take the key out of the key slot */
|
||||
if (PK11_IsInternal(p12ctxt->slot)) {
|
||||
slot = PK11_GetInternalKeySlot();
|
||||
|
@ -1227,10 +1244,15 @@ SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *sa
|
|||
slot = PK11_ReferenceSlot(p12ctxt->slot);
|
||||
}
|
||||
|
||||
epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm,
|
||||
&uniPwitem, cert,
|
||||
NSS_PBE_DEFAULT_ITERATION_COUNT,
|
||||
p12ctxt->wincx);
|
||||
/* passing algorithm as the pbe will force the PBE code to
|
||||
* automatically handle the selection between using the algorithm
|
||||
* as a the pbe algorithm, or using the algorithm as a cipher
|
||||
* and building a pkcs5 pbe */
|
||||
epki = PK11_ExportEncryptedPrivateKeyInfoV2(slot, algorithm,
|
||||
SEC_OID_UNKNOWN, prfAlg,
|
||||
&uniPwitem, cert,
|
||||
NSS_PBE_DEFAULT_ITERATION_COUNT,
|
||||
p12ctxt->wincx);
|
||||
PK11_FreeSlot(slot);
|
||||
if (!epki) {
|
||||
PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY);
|
||||
|
@ -1595,18 +1617,10 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp)
|
|||
SECITEM_ZfreeItem(&pwd, PR_FALSE);
|
||||
|
||||
/* get the PBA Mechanism to generate the key */
|
||||
switch (p12exp->integrityInfo.pwdInfo.algorithm) {
|
||||
case SEC_OID_SHA1:
|
||||
integrityMechType = CKM_PBA_SHA1_WITH_SHA1_HMAC;
|
||||
break;
|
||||
case SEC_OID_MD5:
|
||||
integrityMechType = CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_MD2:
|
||||
integrityMechType = CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
|
||||
break;
|
||||
default:
|
||||
goto loser;
|
||||
integrityMechType = sec_pkcs12_algtag_to_keygen_mech(
|
||||
p12exp->integrityInfo.pwdInfo.algorithm);
|
||||
if (integrityMechType == CKM_INVALID_MECHANISM) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* generate the key */
|
||||
|
@ -1837,7 +1851,8 @@ loser:
|
|||
static SECStatus
|
||||
sec_Pkcs12FinishMac(sec_PKCS12EncoderContext *p12ecx)
|
||||
{
|
||||
SECItem hmac = { siBuffer, NULL, 0 };
|
||||
unsigned char hmacData[HASH_LENGTH_MAX];
|
||||
unsigned int hmacLen;
|
||||
SECStatus rv;
|
||||
SGNDigestInfo *di = NULL;
|
||||
void *dummy;
|
||||
|
@ -1856,13 +1871,8 @@ sec_Pkcs12FinishMac(sec_PKCS12EncoderContext *p12ecx)
|
|||
}
|
||||
|
||||
/* finish the hmac */
|
||||
hmac.data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH);
|
||||
if (!hmac.data) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = PK11_DigestFinal(p12ecx->hmacCx, hmac.data, &hmac.len, SHA1_LENGTH);
|
||||
rv = PK11_DigestFinal(p12ecx->hmacCx, hmacData, &hmacLen, HASH_LENGTH_MAX);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
|
@ -1871,7 +1881,7 @@ sec_Pkcs12FinishMac(sec_PKCS12EncoderContext *p12ecx)
|
|||
|
||||
/* create the digest info */
|
||||
di = SGN_CreateDigestInfo(p12ecx->p12exp->integrityInfo.pwdInfo.algorithm,
|
||||
hmac.data, hmac.len);
|
||||
hmacData, hmacLen);
|
||||
if (!di) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
rv = SECFailure;
|
||||
|
@ -1896,11 +1906,9 @@ loser:
|
|||
if (di) {
|
||||
SGN_DestroyDigestInfo(di);
|
||||
}
|
||||
if (hmac.data) {
|
||||
SECITEM_ZfreeItem(&hmac, PR_FALSE);
|
||||
}
|
||||
PK11_DestroyContext(p12ecx->hmacCx, PR_TRUE);
|
||||
p12ecx->hmacCx = NULL;
|
||||
PORT_Memset(hmacData, 0, hmacLen);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,37 @@ sec_pkcs12_algtag_to_mech(SECOidTag algtag)
|
|||
return CKM_INVALID_MECHANISM;
|
||||
}
|
||||
|
||||
CK_MECHANISM_TYPE
|
||||
sec_pkcs12_algtag_to_keygen_mech(SECOidTag algtag)
|
||||
{
|
||||
switch (algtag) {
|
||||
case SEC_OID_SHA1:
|
||||
return CKM_NSS_PBE_SHA1_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_MD5:
|
||||
return CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_MD2:
|
||||
return CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA224:
|
||||
return CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA256:
|
||||
return CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA384:
|
||||
return CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN;
|
||||
break;
|
||||
case SEC_OID_SHA512:
|
||||
return CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CKM_INVALID_MECHANISM;
|
||||
}
|
||||
|
||||
/* helper functions */
|
||||
/* returns proper bag type template based upon object type tag */
|
||||
const SEC_ASN1Template *
|
||||
|
|
|
@ -38,6 +38,7 @@ extern PRBool sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *de
|
|||
SECItem *src, PRBool zeroTerm,
|
||||
PRBool asciiConvert, PRBool toUnicode);
|
||||
extern CK_MECHANISM_TYPE sec_pkcs12_algtag_to_mech(SECOidTag algtag);
|
||||
extern CK_MECHANISM_TYPE sec_pkcs12_algtag_to_keygen_mech(SECOidTag algtag);
|
||||
|
||||
/* create functions */
|
||||
extern SEC_PKCS12PFXItem *sec_pkcs12_new_pfx(void);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "secoid.h"
|
||||
#include "secport.h"
|
||||
#include "secpkcs5.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#define PKCS12_NULL 0x0000
|
||||
|
||||
|
@ -32,31 +33,32 @@ static pkcs12SuiteMap pkcs12SuiteMaps[] = {
|
|||
};
|
||||
|
||||
/* determine if algid is an algorithm which is allowed */
|
||||
static PRBool
|
||||
sec_PKCS12Allowed(SECOidTag alg)
|
||||
{
|
||||
PRUint32 policy;
|
||||
SECStatus rv;
|
||||
|
||||
rv = NSS_GetAlgorithmPolicy(alg, &policy);
|
||||
if (rv != SECSuccess) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (policy & NSS_USE_ALG_IN_PKCS12) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid)
|
||||
{
|
||||
unsigned int keyLengthBits;
|
||||
SECOidTag algId;
|
||||
int i;
|
||||
|
||||
algId = SEC_PKCS5GetCryptoAlgorithm(algid);
|
||||
if (algId == SEC_OID_UNKNOWN) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
keyLengthBits = (unsigned int)(SEC_PKCS5GetKeyLength(algid) * 8);
|
||||
|
||||
i = 0;
|
||||
while (pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN) {
|
||||
if ((pkcs12SuiteMaps[i].algTag == algId) &&
|
||||
(pkcs12SuiteMaps[i].keyLengthBits == keyLengthBits)) {
|
||||
|
||||
return pkcs12SuiteMaps[i].allowed;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
return sec_PKCS12Allowed(algId);
|
||||
}
|
||||
|
||||
/* is any encryption allowed? */
|
||||
|
@ -65,61 +67,45 @@ SEC_PKCS12IsEncryptionAllowed(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN) {
|
||||
if (pkcs12SuiteMaps[i].allowed == PR_TRUE) {
|
||||
for (i = 0; pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN; i++) {
|
||||
/* we're going to return true here if any of the traditional
|
||||
* algorithms are enabled */
|
||||
if (sec_PKCS12Allowed(pkcs12SuiteMaps[i].algTag)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* keep the traditional enable/disable for old ciphers so old applications
|
||||
* continue to work. This only works for the traditional pkcs12 values,
|
||||
* you need to use NSS_SetAlgorithmPolicy directly for other ciphers. */
|
||||
SECStatus
|
||||
SEC_PKCS12EnableCipher(long which, int on)
|
||||
{
|
||||
int i;
|
||||
SECStatus rv;
|
||||
PRUint32 set = on ? NSS_USE_ALG_IN_PKCS12 : 0;
|
||||
PRUint32 clear = on ? 0 : NSS_USE_ALG_IN_PKCS12;
|
||||
|
||||
i = 0;
|
||||
while (pkcs12SuiteMaps[i].suite != 0L) {
|
||||
for (i = 0; pkcs12SuiteMaps[i].suite != 0L; i++) {
|
||||
if (pkcs12SuiteMaps[i].suite == (unsigned long)which) {
|
||||
if (on) {
|
||||
pkcs12SuiteMaps[i].allowed = PR_TRUE;
|
||||
} else {
|
||||
pkcs12SuiteMaps[i].allowed = PR_FALSE;
|
||||
rv = NSS_SetAlgorithmPolicy(pkcs12SuiteMaps[i].algTag, set, clear);
|
||||
/* could fail if the policy has been locked */
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SEC_PKCS12SetPreferredCipher(long which, int on)
|
||||
{
|
||||
int i;
|
||||
PRBool turnedOff = PR_FALSE;
|
||||
PRBool turnedOn = PR_FALSE;
|
||||
|
||||
i = 0;
|
||||
while (pkcs12SuiteMaps[i].suite != 0L) {
|
||||
if (pkcs12SuiteMaps[i].preferred == PR_TRUE) {
|
||||
pkcs12SuiteMaps[i].preferred = PR_FALSE;
|
||||
turnedOff = PR_TRUE;
|
||||
}
|
||||
if (pkcs12SuiteMaps[i].suite == (unsigned long)which) {
|
||||
pkcs12SuiteMaps[i].preferred = PR_TRUE;
|
||||
turnedOn = PR_TRUE;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((turnedOn) && (turnedOff)) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
return SECFailure;
|
||||
/* nothing looked at the preferences in the suite maps, so this function
|
||||
* has always been a noop */
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "ssl.h"
|
||||
#include "sslerr.h"
|
||||
#include "pk11hpke.h"
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
@ -566,30 +567,33 @@ typedef SECStatus(PR_CALLBACK *SSLResumptionTokenCallback)(
|
|||
/*
|
||||
* Generate an encoded ECHConfig structure (presumably server side).
|
||||
*
|
||||
* configId -- an identifier for the configuration.
|
||||
* publicName -- the public_name value to be placed in SNI.
|
||||
* maxNameLen -- the maximum length of protected names
|
||||
* kemId -- the HKPE KEM ID value
|
||||
* pubKey -- the public key for the key pair
|
||||
* hpkeSuites -- the HPKE cipher suites that can be used
|
||||
* hpkeSuitesCount -- the number of suites in hpkeSuites
|
||||
* kemId -- the HKPE KEM ID value
|
||||
* group -- the named group this key corresponds to
|
||||
* pubKey -- the public key for the key pair
|
||||
* pad -- the maximum length to pad to
|
||||
* out/outlen/maxlen -- where to output the data
|
||||
*/
|
||||
#define SSL_EncodeEchConfig(publicName, hpkeSuites, hpkeSuitesCount, \
|
||||
kemId, pubKey, maxNameLen, out, outlen, \
|
||||
maxlen) \
|
||||
SSL_EXPERIMENTAL_API("SSL_EncodeEchConfig", \
|
||||
(const char *_publicName, \
|
||||
const PRUint32 *_hpkeSuites, \
|
||||
unsigned int _hpkeSuitesCount, \
|
||||
HpkeKemId _kemId, \
|
||||
const SECKEYPublicKey *_pubKey, \
|
||||
PRUint16 _maxNameLen, \
|
||||
PRUint8 *_out, unsigned int *_outlen, \
|
||||
unsigned int _maxlen), \
|
||||
(publicName, hpkeSuites, hpkeSuitesCount, \
|
||||
kemId, pubKey, maxNameLen, out, outlen, \
|
||||
maxlen))
|
||||
typedef struct HpkeSymmetricSuiteStr {
|
||||
HpkeKdfId kdfId;
|
||||
HpkeAeadId aeadId;
|
||||
} HpkeSymmetricSuite;
|
||||
#define SSL_EncodeEchConfigId(configId, publicName, maxNameLen, \
|
||||
kemId, pubKey, hpkeSuites, hpkeSuiteCount, \
|
||||
out, outlen, maxlen) \
|
||||
SSL_EXPERIMENTAL_API("SSL_EncodeEchConfigId", \
|
||||
(PRUint8 _configId, const char *_publicName, \
|
||||
unsigned int _maxNameLen, HpkeKemId _kemId, \
|
||||
const SECKEYPublicKey *_pubKey, \
|
||||
const HpkeSymmetricSuite *_hpkeSuites, \
|
||||
unsigned int _hpkeSuiteCount, \
|
||||
PRUint8 *_out, unsigned int *_outlen, \
|
||||
unsigned int _maxlen), \
|
||||
(configId, publicName, maxNameLen, \
|
||||
kemId, pubKey, hpkeSuites, hpkeSuiteCount, \
|
||||
out, outlen, maxlen))
|
||||
|
||||
/* SSL_SetSecretCallback installs a callback that TLS calls when it installs new
|
||||
* traffic secrets.
|
||||
|
@ -1035,6 +1039,7 @@ typedef struct SSLMaskingContextStr {
|
|||
#define SSL_EnableESNI(a, b, c, d) SSL_DEPRECATED_EXPERIMENTAL_API
|
||||
#define SSL_EncodeESNIKeys(a, b, c, d, e, f, g, h, i, j) SSL_DEPRECATED_EXPERIMENTAL_API
|
||||
#define SSL_SetESNIKeyPair(a, b, c, d) SSL_DEPRECATED_EXPERIMENTAL_API
|
||||
#define SSL_EncodeEchConfig(a, b, c, d, e, f, g, h, i) SSL_DEPRECATED_EXPERIMENTAL_API
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
|
|
|
@ -4296,7 +4296,7 @@ struct {
|
|||
EXP(DestroyResumptionTokenInfo),
|
||||
EXP(EnableTls13BackendEch),
|
||||
EXP(EnableTls13GreaseEch),
|
||||
EXP(EncodeEchConfig),
|
||||
EXP(EncodeEchConfigId),
|
||||
EXP(GetCurrentEpoch),
|
||||
EXP(GetEchRetryConfigs),
|
||||
EXP(GetExtensionSupport),
|
||||
|
|
|
@ -547,7 +547,7 @@ typedef enum {
|
|||
ssl_tls13_short_header_xtn = 0xff03, /* Deprecated. */
|
||||
ssl_tls13_ech_is_inner_xtn = 0xda09,
|
||||
ssl_tls13_outer_extensions_xtn = 0xfd00,
|
||||
ssl_tls13_encrypted_client_hello_xtn = 0xfe09,
|
||||
ssl_tls13_encrypted_client_hello_xtn = 0xfe0a,
|
||||
ssl_tls13_encrypted_sni_xtn = 0xffce, /* Deprecated. */
|
||||
} SSLExtensionType;
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ tls13_DestroyEchXtnState(sslEchXtnState *state)
|
|||
}
|
||||
SECITEM_FreeItem(&state->innerCh, PR_FALSE);
|
||||
SECITEM_FreeItem(&state->senderPubKey, PR_FALSE);
|
||||
SECITEM_FreeItem(&state->configId, PR_FALSE);
|
||||
SECITEM_FreeItem(&state->retryConfigs, PR_FALSE);
|
||||
PORT_ZFree(state, sizeof(*state));
|
||||
}
|
||||
|
@ -103,12 +102,12 @@ tls13_CopyEchConfigs(PRCList *oConfigs, PRCList *configs)
|
|||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
newConfig->contents.configId = config->contents.configId;
|
||||
newConfig->contents.kemId = config->contents.kemId;
|
||||
newConfig->contents.kdfId = config->contents.kdfId;
|
||||
newConfig->contents.aeadId = config->contents.aeadId;
|
||||
newConfig->contents.maxNameLen = config->contents.maxNameLen;
|
||||
newConfig->version = config->version;
|
||||
PORT_Memcpy(newConfig->configId, config->configId, sizeof(newConfig->configId));
|
||||
PR_APPEND_LINK(&newConfig->link, configs);
|
||||
}
|
||||
return SECSuccess;
|
||||
|
@ -119,69 +118,34 @@ loser:
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
tls13_DigestEchConfig(const sslEchConfig *cfg, PRUint8 *digest, size_t maxDigestLen)
|
||||
{
|
||||
SECStatus rv;
|
||||
PK11SymKey *configKey = NULL;
|
||||
PK11SymKey *derived = NULL;
|
||||
SECItem *derivedItem = NULL;
|
||||
CK_HKDF_PARAMS params = { 0 };
|
||||
SECItem paramsi = { siBuffer, (unsigned char *)¶ms, sizeof(params) };
|
||||
PK11SlotInfo *slot = PK11_GetInternalSlot();
|
||||
|
||||
if (!slot) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
configKey = PK11_ImportDataKey(slot, CKM_HKDF_DATA, PK11_OriginUnwrap,
|
||||
CKA_DERIVE, CONST_CAST(SECItem, &cfg->raw), NULL);
|
||||
if (!configKey) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* We only support SHA256 KDF. */
|
||||
PORT_Assert(cfg->contents.kdfId == HpkeKdfHkdfSha256);
|
||||
params.bExtract = CK_TRUE;
|
||||
params.bExpand = CK_TRUE;
|
||||
params.prfHashMechanism = CKM_SHA256;
|
||||
params.ulSaltType = CKF_HKDF_SALT_NULL;
|
||||
params.pInfo = CONST_CAST(CK_BYTE, hHkdfInfoEchConfigID);
|
||||
params.ulInfoLen = strlen(hHkdfInfoEchConfigID);
|
||||
derived = PK11_DeriveWithFlags(configKey, CKM_HKDF_DATA,
|
||||
¶msi, CKM_HKDF_DERIVE, CKA_DERIVE, 8,
|
||||
CKF_SIGN | CKF_VERIFY);
|
||||
|
||||
rv = PK11_ExtractKeyValue(derived);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
derivedItem = PK11_GetKeyData(derived);
|
||||
if (!derivedItem) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (derivedItem->len != maxDigestLen) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
PORT_Memcpy(digest, derivedItem->data, derivedItem->len);
|
||||
PK11_FreeSymKey(configKey);
|
||||
PK11_FreeSymKey(derived);
|
||||
PK11_FreeSlot(slot);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
PK11_FreeSymKey(configKey);
|
||||
PK11_FreeSymKey(derived);
|
||||
if (slot) {
|
||||
PK11_FreeSlot(slot);
|
||||
}
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
* struct {
|
||||
* HpkeKdfId kdf_id;
|
||||
* HpkeAeadId aead_id;
|
||||
* } HpkeSymmetricCipherSuite;
|
||||
*
|
||||
* struct {
|
||||
* uint8 config_id;
|
||||
* HpkeKemId kem_id;
|
||||
* HpkePublicKey public_key;
|
||||
* HpkeSymmetricCipherSuite cipher_suites<4..2^16-4>;
|
||||
* } HpkeKeyConfig;
|
||||
*
|
||||
* struct {
|
||||
* HpkeKeyConfig key_config;
|
||||
* uint16 maximum_name_length;
|
||||
* opaque public_name<1..2^16-1>;
|
||||
* Extension extensions<0..2^16-1>;
|
||||
* } ECHConfigContents;
|
||||
*
|
||||
* struct {
|
||||
* uint16 version;
|
||||
* uint16 length;
|
||||
* select (ECHConfig.version) {
|
||||
* case 0xfe0a: ECHConfigContents contents;
|
||||
* }
|
||||
* } ECHConfig;
|
||||
*/
|
||||
static SECStatus
|
||||
tls13_DecodeEchConfigContents(const sslReadBuffer *rawConfig,
|
||||
sslEchConfig **outConfig)
|
||||
|
@ -199,30 +163,22 @@ tls13_DecodeEchConfigContents(const sslReadBuffer *rawConfig,
|
|||
sslReader extensionReader;
|
||||
PRBool hasValidSuite = PR_FALSE;
|
||||
|
||||
/* Parse the public_name. */
|
||||
rv = sslRead_ReadVariable(&configReader, 2, &tmpBuf);
|
||||
/* HpkeKeyConfig key_config */
|
||||
/* uint8 config_id */
|
||||
rv = sslRead_ReadNumber(&configReader, 1, &tmpn);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
contents.configId = tmpn;
|
||||
|
||||
if (tmpBuf.len == 0) {
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_ECH_CONFIG);
|
||||
/* HpkeKemId kem_id */
|
||||
rv = sslRead_ReadNumber(&configReader, 2, &tmpn);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
for (tmpn = 0; tmpn < tmpBuf.len; tmpn++) {
|
||||
if (tmpBuf.buf[tmpn] == '\0') {
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_ECH_CONFIG);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
contents.kemId = tmpn;
|
||||
|
||||
contents.publicName = PORT_ZAlloc(tmpBuf.len + 1);
|
||||
if (!contents.publicName) {
|
||||
goto loser;
|
||||
}
|
||||
PORT_Memcpy(contents.publicName, (PRUint8 *)tmpBuf.buf, tmpBuf.len);
|
||||
|
||||
/* Public key. */
|
||||
/* HpkePublicKey public_key */
|
||||
rv = sslRead_ReadVariable(&configReader, 2, &tmpBuf);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -232,13 +188,7 @@ tls13_DecodeEchConfigContents(const sslReadBuffer *rawConfig,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
rv = sslRead_ReadNumber(&configReader, 2, &tmpn);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
contents.kemId = tmpn;
|
||||
|
||||
/* Parse HPKE cipher suites. */
|
||||
/* HpkeSymmetricCipherSuite cipher_suites<4..2^16-4> */
|
||||
rv = sslRead_ReadVariable(&configReader, 2, &tmpBuf);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -249,12 +199,12 @@ tls13_DecodeEchConfigContents(const sslReadBuffer *rawConfig,
|
|||
}
|
||||
suiteReader = (sslReader)SSL_READER(tmpBuf.buf, tmpBuf.len);
|
||||
while (SSL_READER_REMAINING(&suiteReader)) {
|
||||
/* kdf_id */
|
||||
/* HpkeKdfId kdf_id */
|
||||
rv = sslRead_ReadNumber(&suiteReader, 2, &tmpn);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
/* aead_id */
|
||||
/* HpkeAeadId aead_id */
|
||||
rv = sslRead_ReadNumber(&suiteReader, 2, &tmpn2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -276,13 +226,36 @@ tls13_DecodeEchConfigContents(const sslReadBuffer *rawConfig,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
/* Read the max name length. */
|
||||
/* uint16 maximum_name_length */
|
||||
rv = sslRead_ReadNumber(&configReader, 2, &tmpn);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
contents.maxNameLen = (PRUint16)tmpn;
|
||||
|
||||
/* opaque public_name<1..2^16-1> */
|
||||
rv = sslRead_ReadVariable(&configReader, 2, &tmpBuf);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (tmpBuf.len == 0) {
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_ECH_CONFIG);
|
||||
goto loser;
|
||||
}
|
||||
for (tmpn = 0; tmpn < tmpBuf.len; tmpn++) {
|
||||
if (tmpBuf.buf[tmpn] == '\0') {
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_ECH_CONFIG);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
contents.publicName = PORT_ZAlloc(tmpBuf.len + 1);
|
||||
if (!contents.publicName) {
|
||||
goto loser;
|
||||
}
|
||||
PORT_Memcpy(contents.publicName, (PRUint8 *)tmpBuf.buf, tmpBuf.len);
|
||||
|
||||
/* Extensions. We don't support any, but must
|
||||
* check for any that are marked critical. */
|
||||
rv = sslRead_ReadVariable(&configReader, 2, &tmpBuf);
|
||||
|
@ -356,7 +329,7 @@ loser:
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Decode an ECHConfigs struct and store each ECHConfig
|
||||
/* Decode an ECHConfigList struct and store each ECHConfig
|
||||
* into |configs|. */
|
||||
SECStatus
|
||||
tls13_DecodeEchConfigs(const SECItem *data, PRCList *configs)
|
||||
|
@ -390,12 +363,12 @@ tls13_DecodeEchConfigs(const SECItem *data, PRCList *configs)
|
|||
/* Handle each ECHConfig. */
|
||||
while (SSL_READER_REMAINING(&configsReader)) {
|
||||
singleConfig.buf = SSL_READER_CURRENT(&configsReader);
|
||||
/* Version */
|
||||
/* uint16 version */
|
||||
rv = sslRead_ReadNumber(&configsReader, 2, &version);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
/* Length */
|
||||
/* uint16 length */
|
||||
rv = sslRead_ReadNumber(&configsReader, 2, &length);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -421,11 +394,6 @@ tls13_DecodeEchConfigs(const SECItem *data, PRCList *configs)
|
|||
goto loser;
|
||||
}
|
||||
|
||||
rv = tls13_DigestEchConfig(decodedConfig, decodedConfig->configId,
|
||||
sizeof(decodedConfig->configId));
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
PR_APPEND_LINK(&decodedConfig->link, configs);
|
||||
decodedConfig = NULL;
|
||||
}
|
||||
|
@ -438,14 +406,14 @@ loser:
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Encode an ECHConfigs structure. We only allow one config, and as the
|
||||
/* Encode an ECHConfigList structure. We only create one config, and as the
|
||||
* primary use for this function is to generate test inputs, we don't
|
||||
* validate against what HPKE and libssl can actually support. */
|
||||
SECStatus
|
||||
SSLExp_EncodeEchConfig(const char *publicName, const PRUint32 *hpkeSuites,
|
||||
unsigned int hpkeSuiteCount, HpkeKemId kemId,
|
||||
const SECKEYPublicKey *pubKey, PRUint16 maxNameLen,
|
||||
PRUint8 *out, unsigned int *outlen, unsigned int maxlen)
|
||||
SSLExp_EncodeEchConfigId(PRUint8 configId, const char *publicName, unsigned int maxNameLen,
|
||||
HpkeKemId kemId, const SECKEYPublicKey *pubKey,
|
||||
const HpkeSymmetricSuite *hpkeSuites, unsigned int hpkeSuiteCount,
|
||||
PRUint8 *out, unsigned int *outlen, unsigned int maxlen)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned int savedOffset;
|
||||
|
@ -460,11 +428,21 @@ SSLExp_EncodeEchConfig(const char *publicName, const PRUint32 *hpkeSuites,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* ECHConfig ECHConfigList<1..2^16-1>; */
|
||||
rv = sslBuffer_Skip(&b, 2, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/*
|
||||
* struct {
|
||||
* uint16 version;
|
||||
* uint16 length;
|
||||
* select (ECHConfig.version) {
|
||||
* case 0xfe0a: ECHConfigContents contents;
|
||||
* }
|
||||
* } ECHConfig;
|
||||
*/
|
||||
rv = sslBuffer_AppendNumber(&b, TLS13_ECH_VERSION, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -475,8 +453,20 @@ SSLExp_EncodeEchConfig(const char *publicName, const PRUint32 *hpkeSuites,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
len = PORT_Strlen(publicName);
|
||||
rv = sslBuffer_AppendVariable(&b, (const PRUint8 *)publicName, len, 2);
|
||||
/*
|
||||
* struct {
|
||||
* uint8 config_id;
|
||||
* HpkeKemId kem_id;
|
||||
* HpkePublicKey public_key;
|
||||
* HpkeSymmetricCipherSuite cipher_suites<4..2^16-4>;
|
||||
* } HpkeKeyConfig;
|
||||
*/
|
||||
rv = sslBuffer_AppendNumber(&b, configId, 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&b, kemId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
@ -490,27 +480,44 @@ SSLExp_EncodeEchConfig(const char *publicName, const PRUint32 *hpkeSuites,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&b, kemId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&b, hpkeSuiteCount * 4, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
for (unsigned int i = 0; i < hpkeSuiteCount; i++) {
|
||||
rv = sslBuffer_AppendNumber(&b, hpkeSuites[i], 4);
|
||||
rv = sslBuffer_AppendNumber(&b, hpkeSuites[i].kdfId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv = sslBuffer_AppendNumber(&b, hpkeSuites[i].aeadId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* struct {
|
||||
* HpkeKeyConfig key_config;
|
||||
* uint16 maximum_name_length;
|
||||
* opaque public_name<1..2^16-1>;
|
||||
* Extension extensions<0..2^16-1>;
|
||||
* } ECHConfigContents;
|
||||
*/
|
||||
rv = sslBuffer_AppendNumber(&b, maxNameLen, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
len = PORT_Strlen(publicName);
|
||||
if (len > 0xffff) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto loser;
|
||||
}
|
||||
rv = sslBuffer_AppendVariable(&b, (const PRUint8 *)publicName, len, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* extensions */
|
||||
rv = sslBuffer_AppendNumber(&b, 0, 2);
|
||||
if (rv != SECSuccess) {
|
||||
|
@ -622,10 +629,6 @@ SSLExp_SetServerEchConfigs(PRFileDesc *fd,
|
|||
const SECKEYPublicKey *pubKey, const SECKEYPrivateKey *privKey,
|
||||
const PRUint8 *echConfigs, unsigned int echConfigsLen)
|
||||
{
|
||||
#ifndef NSS_ENABLE_DRAFT_HPKE
|
||||
PORT_SetError(SSL_ERROR_FEATURE_DISABLED);
|
||||
return SECFailure;
|
||||
#else
|
||||
sslSocket *ss;
|
||||
SECStatus rv;
|
||||
SECItem data = { siBuffer, CONST_CAST(PRUint8, echConfigs), echConfigsLen };
|
||||
|
@ -675,7 +678,6 @@ loser:
|
|||
ss->echPubKey = NULL;
|
||||
ss->echPrivKey = NULL;
|
||||
return SECFailure;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Client enable. For now, we'll use the first
|
||||
|
@ -685,10 +687,6 @@ SSLExp_SetClientEchConfigs(PRFileDesc *fd,
|
|||
const PRUint8 *echConfigs,
|
||||
unsigned int echConfigsLen)
|
||||
{
|
||||
#ifndef NSS_ENABLE_DRAFT_HPKE
|
||||
PORT_SetError(SSL_ERROR_FEATURE_DISABLED);
|
||||
return SECFailure;
|
||||
#else
|
||||
SECStatus rv;
|
||||
sslSocket *ss;
|
||||
SECItem data = { siBuffer, CONST_CAST(PRUint8, echConfigs), echConfigsLen };
|
||||
|
@ -722,7 +720,6 @@ SSLExp_SetClientEchConfigs(PRFileDesc *fd,
|
|||
}
|
||||
|
||||
return SECSuccess;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set up ECH. This generates an ephemeral sender
|
||||
|
@ -823,16 +820,16 @@ loser:
|
|||
|
||||
/*
|
||||
* enum {
|
||||
* encrypted_client_hello(0xfe09), (65535)
|
||||
* encrypted_client_hello(0xfe0a), (65535)
|
||||
* } ExtensionType;
|
||||
*
|
||||
* struct {
|
||||
* HpkeKdfId kdf_id;
|
||||
* HpkeAeadId aead_id;
|
||||
* } ECHCipherSuite;
|
||||
* } HpkeSymmetricCipherSuite;
|
||||
* struct {
|
||||
* ECHCipherSuite cipher_suite;
|
||||
* opaque config_id<0..255>;
|
||||
* HpkeSymmetricCipherSuite cipher_suite;
|
||||
* uint8 config_id;
|
||||
* opaque enc<1..2^16-1>;
|
||||
* opaque payload<1..2^16-1>;
|
||||
* } ClientECH;
|
||||
|
@ -889,18 +886,18 @@ tls13_EncryptClientHello(sslSocket *ss, sslBuffer *outerAAD, sslBuffer *chInner)
|
|||
goto loser;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(chInner, cfg->contents.configId, 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
if (!ss->ssl3.hs.helloRetry) {
|
||||
rv = sslBuffer_AppendVariable(chInner, cfg->configId, sizeof(cfg->configId), 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv = sslBuffer_AppendVariable(chInner, hpkeEnc->data, hpkeEnc->len, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
} else {
|
||||
/* one byte for empty configId, two for empty Enc. */
|
||||
rv = sslBuffer_AppendNumber(chInner, 0, 3);
|
||||
/* |enc| is empty. */
|
||||
rv = sslBuffer_AppendNumber(chInner, 0, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
@ -919,21 +916,18 @@ loser:
|
|||
|
||||
SECStatus
|
||||
tls13_GetMatchingEchConfigs(const sslSocket *ss, HpkeKdfId kdf, HpkeAeadId aead,
|
||||
const SECItem *configId, const sslEchConfig *cur, sslEchConfig **next)
|
||||
const PRUint8 configId, const sslEchConfig *cur, sslEchConfig **next)
|
||||
{
|
||||
PRINT_BUF(50, (ss, "Server GetMatchingEchConfig with digest:",
|
||||
configId->data, configId->len));
|
||||
SSL_TRC(50, ("%d: TLS13[%d]: GetMatchingEchConfig %d",
|
||||
SSL_GETPID(), ss->fd, configId));
|
||||
|
||||
/* If |cur|, resume the search at that node, else the list head. */
|
||||
for (PRCList *cur_p = cur ? ((PRCList *)cur)->next : PR_LIST_HEAD(&ss->echConfigs);
|
||||
cur_p != &ss->echConfigs;
|
||||
cur_p = PR_NEXT_LINK(cur_p)) {
|
||||
sslEchConfig *echConfig = (sslEchConfig *)cur_p;
|
||||
if (configId->len != sizeof(echConfig->configId) ||
|
||||
PORT_Memcmp(echConfig->configId, configId->data, sizeof(echConfig->configId))) {
|
||||
continue;
|
||||
}
|
||||
if (echConfig->contents.aeadId == aead &&
|
||||
if (echConfig->contents.configId == configId &&
|
||||
echConfig->contents.aeadId == aead &&
|
||||
echConfig->contents.kdfId == kdf) {
|
||||
*next = echConfig;
|
||||
return SECSuccess;
|
||||
|
@ -1016,10 +1010,9 @@ tls13_CopyChPreamble(sslReader *reader, const SECItem *explicitSid, sslBuffer *w
|
|||
|
||||
/*
|
||||
* struct {
|
||||
* HpkeKdfId kdfId; // ClientECH.cipher_suite.kdf
|
||||
* HpkeAeadId aeadId; // ClientECH.cipher_suite.aead
|
||||
* opaque config_id<0..255>; // ClientECH.config_id
|
||||
* opaque enc<1..2^16-1>; // ClientECH.enc
|
||||
* HpkeSymmetricCipherSuite cipher_suite; // kdfid_, aead_id
|
||||
* uint8 config_id;
|
||||
* opaque enc<1..2^16-1>;
|
||||
* opaque outer_hello<1..2^24-1>;
|
||||
* } ClientHelloOuterAAD;
|
||||
*/
|
||||
|
@ -1045,17 +1038,17 @@ tls13_MakeChOuterAAD(sslSocket *ss, const SECItem *outer, SECItem *outerAAD)
|
|||
goto loser;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&aad, ss->xtnData.ech->configId, 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (!ss->ssl3.hs.helloRetry) {
|
||||
rv = sslBuffer_AppendVariable(&aad, ss->xtnData.ech->configId.data,
|
||||
ss->xtnData.ech->configId.len, 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv = sslBuffer_AppendVariable(&aad, ss->xtnData.ech->senderPubKey.data,
|
||||
ss->xtnData.ech->senderPubKey.len, 2);
|
||||
} else {
|
||||
/* 1B config_id length, 2B enc length. */
|
||||
rv = sslBuffer_AppendNumber(&aad, 0, 3);
|
||||
/* |enc| is empty for HelloRetryRequest. */
|
||||
rv = sslBuffer_AppendNumber(&aad, 0, 2);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -1506,7 +1499,7 @@ tls13_ConstructClientHelloWithEch(sslSocket *ss, const sslSessionID *sid, PRBool
|
|||
* Post-encryption, we'll assert that this was correct. */
|
||||
encodedChLen = 4 + 1 + 2 + 2 + encodedChInner.len + 16;
|
||||
if (!ss->ssl3.hs.helloRetry) {
|
||||
encodedChLen += 8 + 32; /* configId || enc */
|
||||
encodedChLen += 32; /* enc */
|
||||
}
|
||||
rv = ssl_InsertPaddingExtension(ss, chOuter->len + encodedChLen, chOuterXtnsBuf);
|
||||
if (rv != SECSuccess) {
|
||||
|
@ -1523,12 +1516,12 @@ tls13_ConstructClientHelloWithEch(sslSocket *ss, const sslSessionID *sid, PRBool
|
|||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv = sslBuffer_AppendNumber(&aad, cfg->contents.configId, 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (!ss->ssl3.hs.helloRetry) {
|
||||
rv = sslBuffer_AppendVariable(&aad, cfg->configId, sizeof(cfg->configId), 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
hpkeEnc = PK11_HPKE_GetEncapPubKey(ss->ssl3.hs.echHpkeCtx);
|
||||
if (!hpkeEnc) {
|
||||
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
|
||||
|
@ -1536,8 +1529,8 @@ tls13_ConstructClientHelloWithEch(sslSocket *ss, const sslSessionID *sid, PRBool
|
|||
}
|
||||
rv = sslBuffer_AppendVariable(&aad, hpkeEnc->data, hpkeEnc->len, 2);
|
||||
} else {
|
||||
/* 1B config_id length, 2B enc length. */
|
||||
rv = sslBuffer_AppendNumber(&aad, 0, 3);
|
||||
/* 2B for empty enc length. */
|
||||
rv = sslBuffer_AppendNumber(&aad, 0, 2);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
|
@ -1721,8 +1714,8 @@ tls13_MaybeGreaseEch(sslSocket *ss, unsigned int preambleLen, sslBuffer *buf)
|
|||
SECItem *rawData;
|
||||
CK_HKDF_PARAMS params;
|
||||
SECItem paramsi;
|
||||
/* 1B aead determinant (don't send), 8B config_id, 32B enc, payload */
|
||||
const int kNonPayloadLen = 41;
|
||||
/* 1B aead determinant (don't send), 1B config_id, 32B enc, payload */
|
||||
const int kNonPayloadLen = 34;
|
||||
|
||||
if (!ss->opt.enableTls13GreaseEch || ss->ssl3.hs.echHpkeCtx) {
|
||||
return SECSuccess;
|
||||
|
@ -1787,9 +1780,8 @@ tls13_MaybeGreaseEch(sslSocket *ss, unsigned int preambleLen, sslBuffer *buf)
|
|||
PORT_Assert(rawData->len == kNonPayloadLen + payloadLen);
|
||||
|
||||
/* struct {
|
||||
HpkeKdfId kdf_id;
|
||||
HpkeAeadId aead_id;
|
||||
opaque config_id<0..255>;
|
||||
HpkeSymmetricCipherSuite cipher_suite; // kdf_id, aead_id
|
||||
PRUint8 config_id;
|
||||
opaque enc<1..2^16-1>;
|
||||
opaque payload<1..2^16-1>;
|
||||
} ClientECH; */
|
||||
|
@ -1807,14 +1799,14 @@ tls13_MaybeGreaseEch(sslSocket *ss, unsigned int preambleLen, sslBuffer *buf)
|
|||
goto loser;
|
||||
}
|
||||
|
||||
/* config_id, 8B */
|
||||
rv = sslBuffer_AppendVariable(&greaseBuf, &rawData->data[1], 8, 1);
|
||||
/* config_id */
|
||||
rv = sslBuffer_AppendNumber(&greaseBuf, rawData->data[1], 1);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* enc len is fixed 32B for X25519. */
|
||||
rv = sslBuffer_AppendVariable(&greaseBuf, &rawData->data[9], 32, 2);
|
||||
rv = sslBuffer_AppendVariable(&greaseBuf, &rawData->data[2], 32, 2);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
@ -1958,14 +1950,12 @@ tls13_MaybeHandleEchSignal(sslSocket *ss, const PRUint8 *sh, PRUint32 shLen)
|
|||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
if (ss->ssl3.hs.helloRetry && ss->sec.isServer) {
|
||||
/* Enc and ConfigId are stored in the cookie and must not
|
||||
* be included in CH2.ClientECH. */
|
||||
if (ss->xtnData.ech->senderPubKey.len || ss->xtnData.ech->configId.len) {
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
|
||||
PORT_SetError(SSL_ERROR_BAD_2ND_CLIENT_HELLO);
|
||||
return SECFailure;
|
||||
}
|
||||
/* |enc| must not be included in CH2.ClientECH. */
|
||||
if (ss->ssl3.hs.helloRetry && ss->sec.isServer &&
|
||||
ss->xtnData.ech->senderPubKey.len) {
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
|
||||
PORT_SetError(SSL_ERROR_BAD_2ND_CLIENT_HELLO);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_tls13_encrypted_client_hello_xtn;
|
||||
|
@ -2137,12 +2127,8 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
|
|||
SECStatus rv;
|
||||
SECItem outer = { siBuffer, CONST_CAST(PRUint8, chOuter), chOuterLen };
|
||||
SECItem *decryptedChInner = NULL;
|
||||
SECItem hrrCh1ConfigId = { siBuffer, NULL, 0 };
|
||||
SECItem outerAAD = { siBuffer, NULL, 0 };
|
||||
SECItem cookieData = { siBuffer, NULL, 0 };
|
||||
HpkeContext *ch1EchHpkeCtx = NULL;
|
||||
HpkeKdfId echKdfId;
|
||||
HpkeAeadId echAeadId;
|
||||
sslEchConfig *candidate = NULL; /* non-owning */
|
||||
TLSExtension *hrrXtn;
|
||||
|
||||
|
@ -2160,7 +2146,6 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
PORT_Assert(!ss->xtnData.ech->configId.data);
|
||||
PORT_Assert(!ss->ssl3.hs.echHpkeCtx);
|
||||
|
||||
PRUint8 *tmp = hrrXtn->data.data;
|
||||
|
@ -2174,17 +2159,21 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
|
|||
/* Extract ECH info without restoring hash state. If there's
|
||||
* something wrong with the cookie, continue without ECH
|
||||
* and let HRR code handle the problem. */
|
||||
HpkeContext *ch1EchHpkeCtx = NULL;
|
||||
PRUint8 echConfigId;
|
||||
HpkeKdfId echKdfId;
|
||||
HpkeAeadId echAeadId;
|
||||
rv = tls13_HandleHrrCookie(ss, cookieData.data, cookieData.len,
|
||||
NULL, NULL, NULL, &echKdfId, &echAeadId,
|
||||
&hrrCh1ConfigId, &ch1EchHpkeCtx, PR_FALSE);
|
||||
&echConfigId, &ch1EchHpkeCtx, PR_FALSE);
|
||||
if (rv != SECSuccess) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
ss->xtnData.ech->configId = hrrCh1ConfigId;
|
||||
ss->ssl3.hs.echHpkeCtx = ch1EchHpkeCtx;
|
||||
|
||||
if (echKdfId != ss->xtnData.ech->kdfId ||
|
||||
if (echConfigId != ss->xtnData.ech->configId ||
|
||||
echKdfId != ss->xtnData.ech->kdfId ||
|
||||
echAeadId != ss->xtnData.ech->aeadId) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO,
|
||||
illegal_parameter);
|
||||
|
@ -2197,9 +2186,8 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
|
|||
}
|
||||
|
||||
/* Cookie data was good, proceed with ECH. */
|
||||
PORT_Assert(ss->xtnData.ech->configId.data);
|
||||
rv = tls13_GetMatchingEchConfigs(ss, ss->xtnData.ech->kdfId, ss->xtnData.ech->aeadId,
|
||||
&ss->xtnData.ech->configId, candidate, &candidate);
|
||||
ss->xtnData.ech->configId, candidate, &candidate);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
|
||||
return SECFailure;
|
||||
|
@ -2217,7 +2205,7 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
|
|||
if (rv != SECSuccess) {
|
||||
/* Get the next matching config */
|
||||
rv = tls13_GetMatchingEchConfigs(ss, ss->xtnData.ech->kdfId, ss->xtnData.ech->aeadId,
|
||||
&ss->xtnData.ech->configId, candidate, &candidate);
|
||||
ss->xtnData.ech->configId, candidate, &candidate);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
|
||||
SECITEM_FreeItem(&outerAAD, PR_FALSE);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* - Some of the buffering (construction/compression/decompression) could likely
|
||||
* be optimized, but the spec is still evolving so that work is deferred.
|
||||
*/
|
||||
#define TLS13_ECH_VERSION 0xfe09
|
||||
#define TLS13_ECH_VERSION 0xfe0a
|
||||
#define TLS13_ECH_SIGNAL_LEN 8
|
||||
|
||||
static const char kHpkeInfoEch[] = "tls ech";
|
||||
|
@ -29,21 +29,21 @@ static const char hHkdfInfoEchConfigID[] = "tls ech config id";
|
|||
static const char kHkdfInfoEchConfirm[] = "ech accept confirmation";
|
||||
|
||||
struct sslEchConfigContentsStr {
|
||||
char *publicName;
|
||||
SECItem publicKey; /* NULL on server. Use the keypair in sslEchConfig instead. */
|
||||
PRUint8 configId;
|
||||
HpkeKemId kemId;
|
||||
SECItem publicKey; /* NULL on server. Use the keypair in sslEchConfig instead. */
|
||||
HpkeKdfId kdfId;
|
||||
HpkeAeadId aeadId;
|
||||
SECItem suites; /* One or more HpkeCipherSuites. The selected s
|
||||
* suite is placed in kdfId and aeadId. */
|
||||
PRUint16 maxNameLen;
|
||||
char *publicName;
|
||||
/* No supported extensions. */
|
||||
};
|
||||
|
||||
struct sslEchConfigStr {
|
||||
PRCList link;
|
||||
SECItem raw;
|
||||
PRUint8 configId[8];
|
||||
PRUint16 version;
|
||||
sslEchConfigContents contents;
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ struct sslEchConfigStr {
|
|||
struct sslEchXtnStateStr {
|
||||
SECItem innerCh; /* Server: ClientECH.payload */
|
||||
SECItem senderPubKey; /* Server: ClientECH.enc */
|
||||
SECItem configId; /* Server: ClientECH.config_id */
|
||||
PRUint8 configId; /* Server: ClientECH.config_id */
|
||||
HpkeKdfId kdfId; /* Server: ClientECH.cipher_suite.kdf */
|
||||
HpkeAeadId aeadId; /* Server: ClientECH.cipher_suite.aead */
|
||||
SECItem retryConfigs; /* Client: ServerECH.retry_configs*/
|
||||
|
@ -60,10 +60,10 @@ struct sslEchXtnStateStr {
|
|||
* verified to the ECHConfig public name). */
|
||||
};
|
||||
|
||||
SECStatus SSLExp_EncodeEchConfig(const char *publicName, const PRUint32 *hpkeSuites,
|
||||
unsigned int hpkeSuiteCount, HpkeKemId kemId,
|
||||
const SECKEYPublicKey *pubKey, PRUint16 maxNameLen,
|
||||
PRUint8 *out, unsigned int *outlen, unsigned int maxlen);
|
||||
SECStatus SSLExp_EncodeEchConfigId(PRUint8 configId, const char *publicName, unsigned int maxNameLen,
|
||||
HpkeKemId kemId, const SECKEYPublicKey *pubKey,
|
||||
const HpkeSymmetricSuite *hpkeSuites, unsigned int hpkeSuiteCount,
|
||||
PRUint8 *out, unsigned int *outlen, unsigned int maxlen);
|
||||
SECStatus SSLExp_GetEchRetryConfigs(PRFileDesc *fd, SECItem *retryConfigs);
|
||||
SECStatus SSLExp_SetClientEchConfigs(PRFileDesc *fd, const PRUint8 *echConfigs,
|
||||
unsigned int echConfigsLen);
|
||||
|
|
|
@ -1460,7 +1460,7 @@ tls13_ServerHandleEchXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
HpkeKdfId kdf;
|
||||
HpkeAeadId aead;
|
||||
PRUint32 tmp;
|
||||
SECItem configId;
|
||||
PRUint8 configId;
|
||||
SECItem senderPubKey;
|
||||
SECItem encryptedCh;
|
||||
|
||||
|
@ -1504,11 +1504,12 @@ tls13_ServerHandleEchXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
aead = (HpkeAeadId)tmp;
|
||||
|
||||
/* config_id */
|
||||
rv = ssl3_ExtConsumeHandshakeVariable(ss, &configId, 1,
|
||||
&data->data, &data->len);
|
||||
rv = ssl3_ExtConsumeHandshakeNumber(ss, &tmp, 1,
|
||||
&data->data, &data->len);
|
||||
if (rv != SECSuccess) {
|
||||
goto alert_loser;
|
||||
}
|
||||
configId = tmp;
|
||||
|
||||
/* enc */
|
||||
rv = ssl3_ExtConsumeHandshakeVariable(ss, &senderPubKey, 2,
|
||||
|
@ -1530,7 +1531,7 @@ tls13_ServerHandleEchXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
if (!ss->ssl3.hs.helloRetry) {
|
||||
/* In the real ECH HRR case, config_id and enc should be empty. This
|
||||
* is checked after acceptance, because it might be GREASE ECH. */
|
||||
if (!configId.len || !senderPubKey.len) {
|
||||
if (!senderPubKey.len) {
|
||||
goto alert_loser;
|
||||
}
|
||||
|
||||
|
@ -1538,17 +1539,13 @@ tls13_ServerHandleEchXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
if (rv == SECFailure) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = SECITEM_CopyItem(NULL, &xtnData->ech->configId, &configId);
|
||||
if (rv == SECFailure) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
rv = SECITEM_CopyItem(NULL, &xtnData->ech->innerCh, &encryptedCh);
|
||||
if (rv == SECFailure) {
|
||||
return SECFailure;
|
||||
}
|
||||
xtnData->ech->configId = configId;
|
||||
xtnData->ech->kdfId = kdf;
|
||||
xtnData->ech->aeadId = aead;
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
* uint8 indicator = 0xff; // To disambiguate from tickets.
|
||||
* uint16 cipherSuite; // Selected cipher suite.
|
||||
* uint16 keyShare; // Requested key share group (0=none)
|
||||
* PRUint8 echConfigId; // ECH config_id
|
||||
* HpkeKdfId kdfId; // ECH KDF (uint16)
|
||||
* HpkeAeadId aeadId; // ECH AEAD (uint16)
|
||||
* opaque echConfigId<0..255>; // ECH config_id
|
||||
* opaque echHpkeCtx<0..65535>; // ECH serialized HPKE context
|
||||
* opaque applicationToken<0..65535>; // Application token
|
||||
* opaque ch_hash[rest_of_buffer]; // H(ClientHello)
|
||||
|
@ -63,6 +63,18 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
}
|
||||
|
||||
if (ss->xtnData.ech) {
|
||||
/* Record that we received ECH. */
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, PR_TRUE, 1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->configId,
|
||||
1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->kdfId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
|
@ -72,15 +84,6 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Received ECH config_id, regardless of acceptance or possession
|
||||
* of a matching ECHConfig. */
|
||||
PORT_Assert(ss->xtnData.ech->configId.len == 8);
|
||||
rv = sslBuffer_AppendVariable(&cookieBuf, ss->xtnData.ech->configId.data,
|
||||
ss->xtnData.ech->configId.len, 1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* There might be no HPKE Context, e.g. when we lack a matching ECHConfig. */
|
||||
if (ss->ssl3.hs.echHpkeCtx) {
|
||||
rv = PK11_HPKE_ExportContext(ss->ssl3.hs.echHpkeCtx, NULL, &echHpkeCtx);
|
||||
|
@ -97,7 +100,7 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, 0, 7);
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, PR_FALSE, 1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -132,7 +135,9 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
/* Given a cookie and cookieLen, decrypt and parse, returning
|
||||
* any values that were requested via the "previous_" params. If
|
||||
* recoverState is true, the transcript state and application
|
||||
* token are restored. */
|
||||
* token are restored. Note that previousEchKdfId, previousEchAeadId,
|
||||
* previousEchConfigId, and previousEchHpkeCtx are not modified if ECH was not
|
||||
* previously negotiated (i.e., previousEchOffered is PR_FALSE). */
|
||||
SECStatus
|
||||
tls13_HandleHrrCookie(sslSocket *ss,
|
||||
unsigned char *cookie, unsigned int cookieLen,
|
||||
|
@ -141,7 +146,7 @@ tls13_HandleHrrCookie(sslSocket *ss,
|
|||
PRBool *previousEchOffered,
|
||||
HpkeKdfId *previousEchKdfId,
|
||||
HpkeAeadId *previousEchAeadId,
|
||||
SECItem *previousEchConfigId,
|
||||
PRUint8 *previousEchConfigId,
|
||||
HpkeContext **previousEchHpkeCtx,
|
||||
PRBool recoverState)
|
||||
{
|
||||
|
@ -150,12 +155,13 @@ tls13_HandleHrrCookie(sslSocket *ss,
|
|||
unsigned int plaintextLen = 0;
|
||||
sslBuffer messageBuf = SSL_BUFFER_EMPTY;
|
||||
sslReadBuffer echHpkeBuf = { 0 };
|
||||
sslReadBuffer echConfigIdBuf = { 0 };
|
||||
PRBool receivedEch;
|
||||
PRUint8 echConfigId = 0;
|
||||
PRUint64 sentinel;
|
||||
PRUint64 cipherSuite;
|
||||
HpkeContext *hpkeContext = NULL;
|
||||
HpkeKdfId echKdfId;
|
||||
HpkeAeadId echAeadId;
|
||||
HpkeKdfId echKdfId = 0;
|
||||
HpkeAeadId echAeadId = 0;
|
||||
PRUint64 group;
|
||||
PRUint64 tmp64;
|
||||
const sslNamedGroupDef *selectedGroup;
|
||||
|
@ -190,31 +196,54 @@ tls13_HandleHrrCookie(sslSocket *ss,
|
|||
}
|
||||
selectedGroup = ssl_LookupNamedGroup(group);
|
||||
|
||||
/* ECH Ciphersuite */
|
||||
rv = sslRead_ReadNumber(&reader, 2, &tmp64);
|
||||
/* Was ECH received. */
|
||||
rv = sslRead_ReadNumber(&reader, 1, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
echKdfId = (HpkeKdfId)tmp64;
|
||||
receivedEch = tmp64 == PR_TRUE;
|
||||
|
||||
rv = sslRead_ReadNumber(&reader, 2, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
echAeadId = (HpkeAeadId)tmp64;
|
||||
if (receivedEch) {
|
||||
/* ECH config ID */
|
||||
rv = sslRead_ReadNumber(&reader, 1, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
echConfigId = tmp64;
|
||||
|
||||
/* ECH Config ID and HPKE context may be empty. */
|
||||
rv = sslRead_ReadVariable(&reader, 1, &echConfigIdBuf);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslRead_ReadVariable(&reader, 2, &echHpkeBuf);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
/* ECH Ciphersuite */
|
||||
rv = sslRead_ReadNumber(&reader, 2, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
echKdfId = (HpkeKdfId)tmp64;
|
||||
|
||||
rv = sslRead_ReadNumber(&reader, 2, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
echAeadId = (HpkeAeadId)tmp64;
|
||||
|
||||
/* ECH HPKE context may be empty. */
|
||||
rv = sslRead_ReadVariable(&reader, 2, &echHpkeBuf);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (previousEchHpkeCtx && echHpkeBuf.len) {
|
||||
const SECItem hpkeItem = { siBuffer, CONST_CAST(unsigned char, echHpkeBuf.buf),
|
||||
echHpkeBuf.len };
|
||||
hpkeContext = PK11_HPKE_ImportContext(&hpkeItem, NULL);
|
||||
if (!hpkeContext) {
|
||||
FATAL_ERROR(ss, PORT_GetError(), illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Application token. */
|
||||
|
@ -276,36 +305,6 @@ tls13_HandleHrrCookie(sslSocket *ss,
|
|||
}
|
||||
}
|
||||
|
||||
if (previousEchHpkeCtx && echHpkeBuf.len) {
|
||||
const SECItem hpkeItem = { siBuffer, CONST_CAST(unsigned char, echHpkeBuf.buf),
|
||||
echHpkeBuf.len };
|
||||
hpkeContext = PK11_HPKE_ImportContext(&hpkeItem, NULL);
|
||||
if (!hpkeContext) {
|
||||
FATAL_ERROR(ss, PORT_GetError(), illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
if (previousEchConfigId && echConfigIdBuf.len) {
|
||||
SECItem tmp = { siBuffer, NULL, 0 };
|
||||
rv = SECITEM_MakeItem(NULL, &tmp, echConfigIdBuf.buf, echConfigIdBuf.len);
|
||||
if (rv != SECSuccess) {
|
||||
PK11_HPKE_DestroyContext(hpkeContext, PR_TRUE);
|
||||
FATAL_ERROR(ss, PORT_GetError(), internal_error);
|
||||
return SECFailure;
|
||||
}
|
||||
*previousEchConfigId = tmp;
|
||||
}
|
||||
|
||||
if (previousEchKdfId) {
|
||||
*previousEchKdfId = echKdfId;
|
||||
}
|
||||
if (previousEchAeadId) {
|
||||
*previousEchAeadId = echAeadId;
|
||||
}
|
||||
if (previousEchHpkeCtx) {
|
||||
*previousEchHpkeCtx = hpkeContext;
|
||||
}
|
||||
if (previousCipherSuite) {
|
||||
*previousCipherSuite = cipherSuite;
|
||||
}
|
||||
|
@ -313,7 +312,21 @@ tls13_HandleHrrCookie(sslSocket *ss,
|
|||
*previousGroup = selectedGroup;
|
||||
}
|
||||
if (previousEchOffered) {
|
||||
*previousEchOffered = echConfigIdBuf.len > 0;
|
||||
*previousEchOffered = receivedEch;
|
||||
}
|
||||
if (receivedEch) {
|
||||
if (previousEchConfigId) {
|
||||
*previousEchConfigId = echConfigId;
|
||||
}
|
||||
if (previousEchKdfId) {
|
||||
*previousEchKdfId = echKdfId;
|
||||
}
|
||||
if (previousEchAeadId) {
|
||||
*previousEchAeadId = echAeadId;
|
||||
}
|
||||
if (previousEchHpkeCtx) {
|
||||
*previousEchHpkeCtx = hpkeContext;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ SECStatus tls13_HandleHrrCookie(sslSocket *ss,
|
|||
PRBool *previousEchOffered,
|
||||
HpkeKdfId *previousEchKdfId,
|
||||
HpkeAeadId *previousEchAeadId,
|
||||
SECItem *previousEchConfigId,
|
||||
PRUint8 *previousEchConfigId,
|
||||
HpkeContext **previousEchHpkeCtx,
|
||||
PRBool recoverState);
|
||||
#endif
|
||||
|
|
|
@ -538,7 +538,8 @@ struct SECOidDataStr {
|
|||
#define NSS_USE_ALG_IN_SSL_KX 0x00000004 /* used in SSL key exchange */
|
||||
#define NSS_USE_ALG_IN_SSL 0x00000008 /* used in SSL record protocol */
|
||||
#define NSS_USE_POLICY_IN_SSL 0x00000010 /* enable policy in SSL protocol */
|
||||
#define NSS_USE_ALG_IN_ANY_SIGNATURE 0x00000020 /* used in S/MIME */
|
||||
#define NSS_USE_ALG_IN_ANY_SIGNATURE 0x00000020 /* used in any signature */
|
||||
#define NSS_USE_ALG_IN_PKCS12 0x00000040 /* used in pkcs12 */
|
||||
#define NSS_USE_DEFAULT_NOT_VALID 0x80000000 /* clear to make the default flag valid */
|
||||
#define NSS_USE_DEFAULT_SSL_ENABLE 0x40000000 /* default cipher suite setting 1=enable */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#! /bin/bash
|
||||
#! /bin/bash
|
||||
#
|
||||
# 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
|
||||
|
@ -8,7 +8,7 @@
|
|||
#
|
||||
# mozilla/security/nss/tests/tools/tools.sh
|
||||
#
|
||||
# Script to test basic functionality of NSS tools
|
||||
# Script to test basic functionality of NSS tools
|
||||
#
|
||||
# needs to work on all Unix and Windows platforms
|
||||
#
|
||||
|
@ -23,29 +23,20 @@
|
|||
########################################################################
|
||||
|
||||
export pkcs12v2pbeWithSha1And128BitRc4=\
|
||||
"PKCS #12 V2 PBE With SHA-1 and 128 Bit RC4"
|
||||
"PKCS #12 V2 PBE With SHA-1 And 128 Bit RC4"
|
||||
|
||||
export pkcs12v2pbeWithSha1And40BitRc4=\
|
||||
"PKCS #12 V2 PBE With SHA-1 and 40 Bit RC4"
|
||||
"PKCS #12 V2 PBE With SHA-1 And 40 Bit RC4"
|
||||
|
||||
export pkcs12v2pbeWithSha1AndTripleDESCBC=\
|
||||
"PKCS #12 V2 PBE With SHA-1 and 3KEY Triple DES-CBC"
|
||||
"PKCS #12 V2 PBE With SHA-1 And 3KEY Triple DES-CBC"
|
||||
|
||||
export pkcs12v2pbeWithSha1And128BitRc2Cbc=\
|
||||
"PKCS #12 V2 PBE With SHA-1 and 128 Bit RC2 CBC"
|
||||
"PKCS #12 V2 PBE With SHA-1 And 128 Bit RC2 CBC"
|
||||
|
||||
export pkcs12v2pbeWithSha1And40BitRc2Cbc=\
|
||||
"PKCS #12 V2 PBE With SHA-1 and 40 Bit RC2 CBC"
|
||||
"PKCS #12 V2 PBE With SHA-1 And 40 Bit RC2 CBC"
|
||||
|
||||
export pkcs12v2pbeWithMd2AndDESCBC=\
|
||||
"PKCS #5 Password Based Encryption with MD2 and DES-CBC"
|
||||
|
||||
export pkcs12v2pbeWithMd5AndDESCBC=\
|
||||
"PKCS #5 Password Based Encryption with MD5 and DES-CBC"
|
||||
|
||||
export pkcs12v2pbeWithSha1AndDESCBC=\
|
||||
"PKCS #5 Password Based Encryption with SHA-1 and DES-CBC"
|
||||
|
||||
export pkcs5pbeWithMD2AndDEScbc=\
|
||||
"PKCS #5 Password Based Encryption with MD2 and DES-CBC"
|
||||
|
||||
|
@ -55,8 +46,28 @@
|
|||
export pkcs5pbeWithSha1AndDEScbc=\
|
||||
"PKCS #5 Password Based Encryption with SHA-1 and DES-CBC"
|
||||
|
||||
# if we change the defaults in pk12util, update these variables
|
||||
export CERT_ENCRYPTION_DEFAULT="AES-128-CBC"
|
||||
export KEY_ENCRYPTION_DEFAULT="AES-256-CBC"
|
||||
export HASH_DEFAULT="SHA-256"
|
||||
|
||||
export PKCS5v1_PBE_CIPHERS="${pkcs5pbeWithMD2AndDEScbc},\
|
||||
${pkcs5pbeWithMD5AndDEScbc},\
|
||||
${pkcs5pbeWithSha1AndDEScbc}"
|
||||
export PKCS12_PBE_CIPHERS="${pkcs12v2pbeWithSha1And128BitRc4},\
|
||||
${pkcs12v2pbeWithSha1And40BitRc4},\
|
||||
${pkcs12v2pbeWithSha1AndTripleDESCBC},\
|
||||
${pkcs12v2pbeWithSha1And128BitRc2Cbc},\
|
||||
${pkcs12v2pbeWithSha1And40BitRc2Cbc}"
|
||||
export PKCS5v2_PBE_CIPHERS="RC2-CBC,DES-EDE3-CBC,AES-128-CBC,AES-192-CBC,\
|
||||
AES-256-CBC,CAMELLIA-128-CBC,CAMELLIA-192-CBC,CAMELLIA-256-CBC"
|
||||
export PBE_CIPHERS="${PKCS5v1_PBE_CIPHERS},${PKCS12_PBE_CIPHERS},${PKCS5v2_PBE_CIPHERS}"
|
||||
export PBE_CIPHERS_CLASSES="${pkcs5pbeWithSha1AndDEScbc},\
|
||||
${pkcs12v2pbeWithSha1AndTripleDESCBC},AES-256-CBC,default"
|
||||
export PBE_HASH="SHA-1,SHA-224,SHA-256,SHA-384,SHA-512,default"
|
||||
|
||||
############################## tools_init ##############################
|
||||
# local shell function to initialize this script
|
||||
# local shell function to initialize this script
|
||||
########################################################################
|
||||
tools_init()
|
||||
{
|
||||
|
@ -117,7 +128,7 @@ list_p12_file()
|
|||
{
|
||||
echo "$SCRIPTNAME: Listing Alice's pk12 file"
|
||||
echo "pk12util -l ${1} -w ${R_PWFILE}"
|
||||
|
||||
|
||||
${BINDIR}/pk12util -l ${1} -w ${R_PWFILE} 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Listing ${1} (pk12util -l)"
|
||||
|
@ -131,105 +142,70 @@ import_p12_file()
|
|||
{
|
||||
echo "$SCRIPTNAME: Importing Alice's pk12 ${1} file"
|
||||
echo "pk12util -i ${1} -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}"
|
||||
|
||||
|
||||
${BINDIR}/pk12util -i ${1} -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Importing ${1} (pk12util -i)"
|
||||
check_tmpfile
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Export the key and cert to a p12 file using default ciphers
|
||||
########################################################################
|
||||
export_with_default_ciphers()
|
||||
{
|
||||
echo "$SCRIPTNAME: Exporting Alice's key & cert with [default:default] (pk12util -o)"
|
||||
echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE}"
|
||||
${BINDIR}/pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} \
|
||||
-k ${R_PWFILE} -w ${R_PWFILE} 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting Alices's key & cert with [default:default] (pk12util -o)"
|
||||
check_tmpfile
|
||||
return $ret
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Exports key/cert to a p12 file, the key encryption cipher is specified
|
||||
# and the cert encryption cipher is blank for default.
|
||||
# Export the key and cert from the specified p12 file
|
||||
########################################################################
|
||||
export_with_key_cipher()
|
||||
export_p12_file()
|
||||
{
|
||||
# $1 key encryption cipher
|
||||
echo "$SCRIPTNAME: Exporting with [${1}:default]"
|
||||
echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -c ${1}"
|
||||
${BINDIR}/pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} \
|
||||
-k ${R_PWFILE} -w ${R_PWFILE} -c "${1}" 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting with [${1}:default] (pk12util -o)"
|
||||
check_tmpfile
|
||||
return $ret
|
||||
}
|
||||
# $1 p12 file
|
||||
# $2 cert to export
|
||||
# $3 certdb
|
||||
# $4 key encryption cipher or "default"
|
||||
# $5 certificate encryption cipher or "default"
|
||||
# $6 hash algorithm or "default"
|
||||
KEY_CIPHER_OPT="-c"
|
||||
KEY_CIPHER="${4}"
|
||||
CERT_CIPHER_OPT="-C"
|
||||
CERT_CIPHER="${5}"
|
||||
HASH_ALG_OPT="-M"
|
||||
HASH_ALG="${6}"
|
||||
|
||||
########################################################################
|
||||
# Exports key/cert to a p12 file, the key encryption cipher is left
|
||||
# empty for default and the cert encryption cipher is specified.
|
||||
########################################################################
|
||||
export_with_cert_cipher()
|
||||
{
|
||||
# $1 certificate encryption cipher
|
||||
echo "$SCRIPTNAME: Exporting with [default:${1}]"
|
||||
echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -C ${1}"
|
||||
${BINDIR}/pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} \
|
||||
-k ${R_PWFILE} -w ${R_PWFILE} -C "${1}" 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting with [default:${1}] (pk12util -o)"
|
||||
check_tmpfile
|
||||
return $ret
|
||||
}
|
||||
if [ "${KEY_CIPHER}" = "default" ]; then
|
||||
KEY_CIPHER_OPT=""
|
||||
KEY_CIPHER=""
|
||||
fi
|
||||
if [ "${CERT_CIPHER}" = "default" ]; then
|
||||
CERT_CIPHER_OPT=""
|
||||
CERT_CIPHER=""
|
||||
fi
|
||||
if [ "${HASH_ALG}" = "default" ]; then
|
||||
HASH_ALG_OPT=""
|
||||
HASH_ALG=""
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# Exports key/cert to a p12 file, both the key encryption cipher and
|
||||
# the cert encryption cipher are specified.
|
||||
########################################################################
|
||||
export_with_both_key_and_cert_cipher()
|
||||
{
|
||||
# $1 key encryption cipher or ""
|
||||
# $2 certificate encryption cipher or ""
|
||||
|
||||
echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -c ${1} -C ${2}"
|
||||
${BINDIR}/pk12util -o Alice.p12 -n Alice -d ${P_R_ALICEDIR} \
|
||||
echo "pk12util -o \"${1}\" -n \"${2}\" -d \"${3}\" \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} \\"
|
||||
echo " ${KEY_CIPHER_OPT} \"${KEY_CIPHER}\" \\"
|
||||
echo " ${CERT_CIPHER_OPT} \"${CERT_CIPHER}\" \\"
|
||||
echo " ${HASH_ALG_OPT} \"${HASH_ALG}\""
|
||||
${BINDIR}/pk12util -o "${1}" -n "${2}" -d "${3}" \
|
||||
-k ${R_PWFILE} -w ${R_PWFILE} \
|
||||
-c "${1}" -C "${2}" 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting with [${1}:${2}] (pk12util -o)"
|
||||
${KEY_CIPHER_OPT} "${KEY_CIPHER}" \
|
||||
${CERT_CIPHER_OPT} "${CERT_CIPHER}" \
|
||||
${HASH_ALG_OPT} "${HASH_ALG}" 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting with [${4}:${5}:${6}] (pk12util -o)"
|
||||
check_tmpfile
|
||||
verify_p12 "${1}" "${4}" "${5}" "${6}"
|
||||
return $ret
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Exports key and cert to a p12 file, both the key encryption cipher
|
||||
# and the cert encryption cipher are specified. The key and cert are
|
||||
# imported and the p12 file is listed
|
||||
# Exports key and cert to a p12 file, the key encryption cipher,
|
||||
# the cert encryption cipher, and/or the hash algorithm are specified.
|
||||
# The key and cert are imported and the p12 file is listed
|
||||
########################################################################
|
||||
export_list_import()
|
||||
{
|
||||
# $1 key encryption cipher
|
||||
# $2 certificate encryption cipher
|
||||
|
||||
if [ "${1}" != "DEFAULT" -a "${2}" != "DEFAULT" ]; then
|
||||
export_with_both_key_and_cert_cipher "${1}" "${2}"
|
||||
elif [ "${1}" != "DEFAULT" -a "${2}" = "DEFAULT" ]; then
|
||||
export_with_key_cipher "${1}"
|
||||
elif [ "${1}" = "DEFAULT" -a "${2}" != "DEFAULT" ]; then
|
||||
export_with_cert_cipher "${2}"
|
||||
else
|
||||
export_with_default_ciphers
|
||||
fi
|
||||
|
||||
export_p12_file Alice.p12 Alice "${P_R_ALICEDIR}" "${@}"
|
||||
list_p12_file Alice.p12
|
||||
import_p12_file Alice.p12
|
||||
}
|
||||
|
@ -239,20 +215,17 @@ export_list_import()
|
|||
# List the contents of and import from the p12 file.
|
||||
########################################################################
|
||||
tools_p12_export_list_import_all_pkcs5pbe_ciphers()
|
||||
{
|
||||
# specify each on key and cert cipher
|
||||
for key_cipher in "${pkcs5pbeWithMD2AndDEScbc}" \
|
||||
"${pkcs5pbeWithMD5AndDEScbc}" \
|
||||
"${pkcs5pbeWithSha1AndDEScbc}"\
|
||||
"DEFAULT"; do
|
||||
for cert_cipher in "${pkcs5pbeWithMD2AndDEScbc}" \
|
||||
"${pkcs5pbeWithMD5AndDEScbc}" \
|
||||
"${pkcs5pbeWithSha1AndDEScbc}" \
|
||||
"DEFAULT"\
|
||||
"none"; do
|
||||
export_list_import "${key_cipher}" "${cert_cipher}"
|
||||
done
|
||||
{
|
||||
local saveIFS="${IFS}"
|
||||
IFS=,
|
||||
for key_cipher in ${PKCS5v1_PBE_CIPHERS} default; do
|
||||
for cert_cipher in ${PKCS5v1_PBE_CIPHERS} default none; do
|
||||
for hash in ${PBE_HASH}; do
|
||||
export_list_import "${key_cipher}" "${cert_cipher}" "${hash}"
|
||||
done
|
||||
done
|
||||
done
|
||||
IFS="${saveIFS}"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
|
@ -261,36 +234,16 @@ tools_p12_export_list_import_all_pkcs5pbe_ciphers()
|
|||
########################################################################
|
||||
tools_p12_export_list_import_all_pkcs5v2_ciphers()
|
||||
{
|
||||
# These should pass
|
||||
for key_cipher in\
|
||||
RC2-CBC \
|
||||
DES-EDE3-CBC \
|
||||
AES-128-CBC \
|
||||
AES-192-CBC \
|
||||
AES-256-CBC \
|
||||
CAMELLIA-128-CBC \
|
||||
CAMELLIA-192-CBC \
|
||||
CAMELLIA-256-CBC; do
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Bug 452464 - pk12util -o fails when -C option specifies
|
||||
# Camellia ciphers
|
||||
# FIXME Restore these to the list
|
||||
# CAMELLIA-128-CBC, \
|
||||
# CAMELLIA-192-CBC, \
|
||||
# CAMELLIA-256-CBC, \
|
||||
# when 452464 is fixed
|
||||
#---------------------------------------------------------------
|
||||
for cert_cipher in \
|
||||
RC2-CBC \
|
||||
DES-EDE3-CBC \
|
||||
AES-128-CBC \
|
||||
AES-192-CBC \
|
||||
AES-256-CBC \
|
||||
none; do
|
||||
export_list_import ${key_cipher} ${cert_cipher}
|
||||
done
|
||||
local saveIFS="${IFS}"
|
||||
IFS=,
|
||||
for key_cipher in ${PKCS5v2_PBE_CIPHERS} default; do
|
||||
for cert_cipher in ${PKCS5v2_PBE_CIPHERS} default none; do
|
||||
for hash in ${PBE_HASH}; do
|
||||
export_list_import "${key_cipher}" "${cert_cipher}" "${hash}"
|
||||
done
|
||||
done
|
||||
done
|
||||
IFS="${saveIFS}"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
|
@ -298,36 +251,50 @@ tools_p12_export_list_import_all_pkcs5v2_ciphers()
|
|||
# List the contents of and import from the p12 file.
|
||||
########################################################################
|
||||
tools_p12_export_list_import_all_pkcs12v2pbe_ciphers()
|
||||
{
|
||||
#---------------------------------------------------------------
|
||||
# Bug 452471 - pk12util -o fails when -c option specifies pkcs12v2 PBE ciphers
|
||||
# FIXME - Restore these to the list
|
||||
# "${pkcs12v2pbeWithSha1And128BitRc4}" \
|
||||
# "${pkcs12v2pbeWithSha1And40BitRc4}" \
|
||||
# "${pkcs12v2pbeWithSha1AndTripleDESCBC}" \
|
||||
# "${pkcs12v2pbeWithSha1And128BitRc2Cbc}" \
|
||||
# "${pkcs12v2pbeWithSha1And40BitRc2Cbc}" \
|
||||
# "${pkcs12v2pbeWithMd2AndDESCBC}" \
|
||||
# "${pkcs12v2pbeWithMd5AndDESCBC}" \
|
||||
# "${pkcs12v2pbeWithSha1AndDESCBC}" \
|
||||
# "DEFAULT"; do
|
||||
# when 452471 is fixed
|
||||
#---------------------------------------------------------------
|
||||
# for key_cipher in \
|
||||
key_cipher="DEFAULT"
|
||||
for cert_cipher in "${pkcs12v2pbeWithSha1And128BitRc4}" \
|
||||
"${pkcs12v2pbeWithSha1And40BitRc4}" \
|
||||
"${pkcs12v2pbeWithSha1AndTripleDESCBC}" \
|
||||
"${pkcs12v2pbeWithSha1And128BitRc2Cbc}" \
|
||||
"${pkcs12v2pbeWithSha1And40BitRc2Cbc}" \
|
||||
"${pkcs12v2pbeWithMd2AndDESCBC}" \
|
||||
"${pkcs12v2pbeWithMd5AndDESCBC}" \
|
||||
"${pkcs12v2pbeWithSha1AndDESCBC}" \
|
||||
"DEFAULT"\
|
||||
"none"; do
|
||||
export_list_import "${key_cipher}" "${cert_cipher}"
|
||||
done
|
||||
#done
|
||||
{
|
||||
local saveIFS="${IFS}"
|
||||
IFS=,
|
||||
for key_cipher in ${PKCS12_PBE_CIPHERS} ${PKCS5v1_PBE_CIPHERS} default; do
|
||||
for cert_cipher in ${PKCS12_PBE_CIPHERS} ${PKCS5v1_PBE_CIPHERS} default none; do
|
||||
for hash in ${PBE_HASH}; do
|
||||
export_list_import "${key_cipher}" "${cert_cipher}" "${hash}"
|
||||
done
|
||||
done
|
||||
done
|
||||
IFS="${saveIFS}"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Spot check all ciphers.
|
||||
# using the traditional tests, we wind up running almost 1300 tests.
|
||||
# This isn't too bad for debug builds in which the interator is set to 1000.
|
||||
# for optimized builds, the iterator is set to 60000, which means a 30
|
||||
# minute test will now take more than 2 hours. This tests most combinations
|
||||
# and results in only about 300 tests. We are stil testing all ciphers
|
||||
# for both key and cert encryption, and we are testing them against
|
||||
# one of each class of cipher (pkcs5v1, pkcs5v2, pkcs12).
|
||||
########################################################################
|
||||
tools_p12_export_list_import_most_ciphers()
|
||||
{
|
||||
local saveIFS="${IFS}"
|
||||
IFS=,
|
||||
for cipher in ${PBE_CIPHERS}; do
|
||||
for class in ${PBE_CIPHERS_CLASSES}; do
|
||||
# we'll test the case of cipher == class below the for loop
|
||||
if [ "${cipher}" != "${class}" ]; then
|
||||
export_list_import "${class}" "${cipher}" "SHA-1"
|
||||
export_list_import "${cipher}" "${class}" "SHA-256"
|
||||
fi
|
||||
done
|
||||
export_list_import "${cipher}" "none" "SHA-224"
|
||||
export_list_import "${cipher}" "${cipher}" "SHA-384"
|
||||
done
|
||||
for class in ${PBE_CIPHERS_CLASSES}; do
|
||||
for hash in ${PBE_HASH}; do
|
||||
export_list_import "${class}" "${class}" "${hash}"
|
||||
done
|
||||
done
|
||||
IFS="${saveIFS}"
|
||||
}
|
||||
|
||||
#########################################################################
|
||||
|
@ -337,28 +304,28 @@ tools_p12_export_with_none_ciphers()
|
|||
{
|
||||
# use none as the key encryption algorithm default for the cert one
|
||||
# should fail
|
||||
|
||||
|
||||
echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -c none"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -c none"
|
||||
${BINDIR}/pk12util -o Alice.p12 -n Alice -d ${P_R_ALICEDIR} \
|
||||
-k ${R_PWFILE} -w ${R_PWFILE} \
|
||||
-c none 2>&1
|
||||
-c none 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 30 "Exporting with [none:default] (pk12util -o)"
|
||||
html_msg $ret 30 "Exporting with [none:default:default] (pk12util -o)"
|
||||
check_tmpfile
|
||||
|
||||
# use default as the key encryption algorithm none for the cert one
|
||||
# should pass
|
||||
|
||||
|
||||
echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} \\"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -C none"
|
||||
echo " -k ${R_PWFILE} -w ${R_PWFILE} -C none"
|
||||
${BINDIR}/pk12util -o Alice.p12 -n Alice -d ${P_R_ALICEDIR} \
|
||||
-k ${R_PWFILE} -w ${R_PWFILE} \
|
||||
-C none 2>&1
|
||||
-C none 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting with [default:none] (pk12util -o)"
|
||||
html_msg $ret 0 "Exporting with [default:none:default] (pk12util -o)"
|
||||
check_tmpfile
|
||||
|
||||
verify_p12 Alice.p12 "default" "none" "default"
|
||||
}
|
||||
|
||||
#########################################################################
|
||||
|
@ -394,17 +361,18 @@ tools_p12_export_with_invalid_ciphers()
|
|||
tools_p12_export_list_import_with_default_ciphers()
|
||||
{
|
||||
echo "$SCRIPTNAME: Exporting Alice's email cert & key - default ciphers"
|
||||
|
||||
export_list_import "DEFAULT" "DEFAULT"
|
||||
|
||||
export_list_import "default" "default" "default"
|
||||
|
||||
echo "$SCRIPTNAME: Exporting Alice's email EC cert & key---------------"
|
||||
echo "pk12util -o Alice-ec.p12 -n \"Alice-ec\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\"
|
||||
echo " -w ${R_PWFILE}"
|
||||
${BINDIR}/pk12util -o Alice-ec.p12 -n "Alice-ec" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \
|
||||
-w ${R_PWFILE} 2>&1
|
||||
-w ${R_PWFILE} 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Exporting Alice's email EC cert & key (pk12util -o)"
|
||||
check_tmpfile
|
||||
verify_p12 Alice-ec.p12 "default" "default" "default"
|
||||
|
||||
echo "$SCRIPTNAME: Importing Alice's email EC cert & key --------------"
|
||||
echo "pk12util -i Alice-ec.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}"
|
||||
|
@ -460,9 +428,18 @@ tools_p12_import_rsa_pss_private_key()
|
|||
tools_p12()
|
||||
{
|
||||
tools_p12_export_list_import_with_default_ciphers
|
||||
tools_p12_export_list_import_all_pkcs5v2_ciphers
|
||||
tools_p12_export_list_import_all_pkcs5pbe_ciphers
|
||||
tools_p12_export_list_import_all_pkcs12v2pbe_ciphers
|
||||
# optimized builds have a larger iterator, so they can't run as many
|
||||
# pkcs12 tests and complete in a reasonable time. Use the iterateration
|
||||
# count from the previous tests to determine how many tests
|
||||
# we can run.
|
||||
iteration_count=$(pp -t p12 -i Alice-ec.p12 | grep "Iterations: " | sed -e 's;.*Iterations: ;;' -e 's;(.*).*;;')
|
||||
echo "Iteration count=${iteration_count}"
|
||||
if [ -n "${iteration_count}" -a ${iteration_count} -le 10000 ]; then
|
||||
tools_p12_export_list_import_all_pkcs5v2_ciphers
|
||||
tools_p12_export_list_import_all_pkcs12v2pbe_ciphers
|
||||
else
|
||||
tools_p12_export_list_import_most_ciphers
|
||||
fi
|
||||
tools_p12_export_with_none_ciphers
|
||||
tools_p12_export_with_invalid_ciphers
|
||||
tools_p12_import_old_files
|
||||
|
@ -473,7 +450,7 @@ tools_p12()
|
|||
|
||||
############################## tools_sign ##############################
|
||||
# local shell function pk12util uses a hardcoded tmp file, if this exists
|
||||
# and is owned by another user we don't get reasonable errormessages
|
||||
# and is owned by another user we don't get reasonable errormessages
|
||||
########################################################################
|
||||
check_tmpfile()
|
||||
{
|
||||
|
@ -483,6 +460,163 @@ check_tmpfile()
|
|||
fi
|
||||
}
|
||||
|
||||
############################## tools_sign ##############################
|
||||
# make sure the generated p12 file has the characteristics we expected
|
||||
########################################################################
|
||||
verify_p12()
|
||||
{
|
||||
KEY_ENCRYPTION=$(map_cipher "${2}" "${KEY_ENCRYPTION_DEFAULT}")
|
||||
CERT_ENCRYPTION=$(map_cipher "${3}" "${CERT_ENCRYPTION_DEFAULT}")
|
||||
HASH=$(map_cipher "${4}" "${HASH_DEFAULT}")
|
||||
|
||||
STATE="NOBAGS" # state records if we are in the key or cert bag
|
||||
CERT_ENCRYPTION_NOT_FOUND=1
|
||||
KEY_ENCRYPTION_NOT_FOUND=1
|
||||
CERT_ENCRYPTION_FAIL=0
|
||||
KEY_ENCRYPTION_FAIL=0
|
||||
HASH_FAIL=0
|
||||
TMP=$(mktemp /tmp/p12Verify.XXXXXX)
|
||||
which pk12util
|
||||
local saveIFS="${IFS}"
|
||||
IFS=" \
|
||||
"
|
||||
# use pp to dump the pkcs12 file, only the unencrypted portions are visible
|
||||
# if there are multiple entries, we fail if any of those entries have the
|
||||
# wrong encryption. We also fail if we can't find any encryption info.
|
||||
# Use a file rather than a pipe so that while do can modify our variables.
|
||||
# We're only interested in extracting the encryption algorithms are here,
|
||||
# p12util -l will verify that decryption works properly.
|
||||
pp -t pkcs12 -i ${1} -o ${TMP}
|
||||
while read line ; do
|
||||
# first up: if we see an unencrypted key bag, then we know that the key
|
||||
# was unencrypted (NOTE: pk12util currently can't generate these kinds of
|
||||
# files).
|
||||
if [[ "${line}" =~ "Bag "[0-9]+" ID: PKCS #12 V1 Key Bag" ]]; then
|
||||
KEY_ENCRYPTION_NOT_FOUND=0
|
||||
if [ "${KEY_ENCRYPTION}" != "none" ]; then
|
||||
KEY_ENCRYPTION_FAIL=1
|
||||
echo "--Key encryption mismatch: expected \"${KEY_ENCRYPTION}\" found \"none\""
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
# if we find the the Cert Bag, then we know that the certificate was not
|
||||
# encrypted
|
||||
if [[ "${line}" =~ "Bag "[0-9]+" ID: PKCS #12 V1 Cert Bag" ]]; then
|
||||
CERT_ENCRYPTION_NOT_FOUND=0
|
||||
if [ "${CERT_ENCRYPTION}" != "none" ]; then
|
||||
CERT_ENCRYPTION_FAIL=1
|
||||
echo "--Cert encryption mismatch: expected \"${CERT_ENCRYPTION}\" found \"none\""
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
# we found the shrouded key bag, the next encryption informtion should be
|
||||
# for the key.
|
||||
if [[ "${line}" =~ "Bag "[0-9]+" ID: PKCS #12 V1 PKCS8 Shrouded Key Bag" ]]; then
|
||||
STATE="KEY"
|
||||
continue
|
||||
fi
|
||||
# If we found PKCS #7 Encrypted Data, it must be the encrypted certificate
|
||||
# (well it could be any encrypted certificate, or a crl, but in p12util
|
||||
# they will all have the same encryption value
|
||||
if [[ "${line}" = "PKCS #7 Encrypted Data:" ]]; then
|
||||
STATE="CERT"
|
||||
continue
|
||||
fi
|
||||
# check the Mac
|
||||
if [[ "${line}" =~ "Mac Digest Algorithm ID: ".* ]]; then
|
||||
MAC="${line##Mac Digest Algorithm ID: }"
|
||||
if [ "${MAC}" != "${HASH}" ]; then
|
||||
HASH_FAIL=1
|
||||
echo "--Mac Hash mismatch: expected \"${HASH}\" found \"${MAC}\""
|
||||
fi
|
||||
fi
|
||||
# check the KDF
|
||||
if [[ "${line}" =~ "KDF algorithm: ".* ]]; then
|
||||
KDF="${line##KDF algorithm: }"
|
||||
if [ "${KDF}" != "HMAC ${HASH}" ]; then
|
||||
HASH_FAIL=1
|
||||
echo "--KDF Hash mismatch: expected \"HMAC ${HASH}\" found \"${KDF}\""
|
||||
fi
|
||||
fi
|
||||
# Content Encryption Algorithm is the PKCS #5 algorithm ID.
|
||||
if [[ "${line}" =~ .*"Encryption Algorithm: ".* ]]; then
|
||||
# Strip the [Content ]EncryptionAlgorithm
|
||||
ENCRYPTION="${line##Content }"
|
||||
ENCRYPTION="${ENCRYPTION##Encryption Algorithm: }"
|
||||
# If that algorithm id is PKCS #5 V2, then skip forward looking
|
||||
# for the Cipher: field.
|
||||
if [[ "${ENCRYPTION}" =~ "PKCS #5 Password Based Encryption v2"\ * ]]; then
|
||||
continue;
|
||||
fi
|
||||
case ${STATE} in
|
||||
"KEY")
|
||||
KEY_ENCRYPTION_NOT_FOUND=0
|
||||
if [ "${KEY_ENCRYPTION}" != "${ENCRYPTION}" ]; then
|
||||
KEY_ENCRYPTION_FAIL=1
|
||||
echo "--Key encryption mismatch: expected \"${KEY_ENCRYPTION}\" found \"${ENCRYPTION}\""
|
||||
fi
|
||||
;;
|
||||
"CERT")
|
||||
CERT_ENCRYPTION_NOT_FOUND=0
|
||||
if [ "${CERT_ENCRYPTION}" != "${ENCRYPTION}" ]; then
|
||||
CERT_ENCRYPTION_FAIL=1
|
||||
echo "--Cert encryption mismatch: expected \"${CERT_ENCRYPTION}\" found \"${ENCRYPTION}\""
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# handle the PKCS 5 case
|
||||
if [[ "${line}" =~ "Cipher: ".* ]]; then
|
||||
ENCRYPTION="${line#Cipher: }"
|
||||
case ${STATE} in
|
||||
"KEY")
|
||||
KEY_ENCRYPTION_NOT_FOUND=0
|
||||
if [ "${KEY_ENCRYPTION}" != "${ENCRYPTION}" ]; then
|
||||
KEY_ENCRYPTION_FAIL=1
|
||||
echo "--Key encryption mismatch: expected \"${KEY_ENCRYPTION}\" found \"${ENCRYPTION}\""
|
||||
fi
|
||||
;;
|
||||
"CERT")
|
||||
CERT_ENCRYPTION_NOT_FOUND=0
|
||||
if [ "${CERT_ENCRYPTION}" != "${ENCRYPTION}" ]; then
|
||||
CERT_ENCRYPTION_FAIL=1
|
||||
echo "--Cert encryption mismatch: expected \"${CERT_ENCRYPTION}\" found \"${ENCRYPTION}\""
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done < ${TMP}
|
||||
IFS="${saveIFS}"
|
||||
# we've scanned the file, set the return value to a combination of
|
||||
# KEY and CERT state variables. If everything is as expected, they should
|
||||
# add up to 0.
|
||||
ret=$((${HASH_FAIL} * 10000 + ${KEY_ENCRYPTION_FAIL} * 1000 + ${KEY_ENCRYPTION_NOT_FOUND} * 100 + ${CERT_ENCRYPTION_FAIL} * 10 + ${CERT_ENCRYPTION_NOT_FOUND}))
|
||||
rm -r ${TMP}
|
||||
html_msg $ret 0 "Verifying p12 file generated with [${2}:${3}:${4}]"
|
||||
}
|
||||
|
||||
#
|
||||
# this handles any mapping we need from requested cipher to
|
||||
# actual cipher. For instance ciphers which already have
|
||||
# PKCS 5 v1 PBE will be mapped to those pbes by pk12util.
|
||||
map_cipher()
|
||||
{
|
||||
if [ "${1}" = "default" ]; then
|
||||
echo "${2}"
|
||||
return
|
||||
fi
|
||||
case "${1}" in
|
||||
# these get mapped to the PKCS5 v1 or PKCS 12 attributes, not PKCS 5v2
|
||||
RC2-CBC)
|
||||
echo "${pkcs12v2pbeWithSha1And128BitRc2Cbc}"
|
||||
return ;;
|
||||
DES-EDE3-CBC)
|
||||
echo "${pkcs12v2pbeWithSha1AndTripleDESCBC}"
|
||||
return;;
|
||||
esac
|
||||
echo "${1}"
|
||||
}
|
||||
|
||||
############################## tools_sign ##############################
|
||||
# local shell function to test basic functionality of signtool
|
||||
########################################################################
|
||||
|
@ -554,7 +688,7 @@ tools_modutil()
|
|||
}
|
||||
|
||||
############################## tools_cleanup ###########################
|
||||
# local shell function to finish this script (no exit since it might be
|
||||
# local shell function to finish this script (no exit since it might be
|
||||
# sourced)
|
||||
########################################################################
|
||||
tools_cleanup()
|
||||
|
|
Загрузка…
Ссылка в новой задаче