Bug 1020695: Update Mozilla to use NSS 3.16.2 Beta 3. Includes fixes for

bug 1013088, bug 996237, bug 970539, bug 1016567, bug 485732, bug 334013,
bug 959864, bug 1016836, bug 1016811, bug 1018536, bug 996250, bug 1009227,
bug 963150.
This commit is contained in:
Wan-Teh Chang 2014-06-04 21:03:47 -07:00
parent dce20d18a7
commit a1f15c3eeb
30 changed files with 1533 additions and 609 deletions

View File

@ -1 +1 @@
NSS_3_16_2_BETA2
NSS_3_16_2_BETA3

View File

@ -92,6 +92,10 @@ static void Usage(char *progName)
"-i input");
fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
"-o output");
fprintf(stderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
"-w suffix");
fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
"");
exit(-1);
}
@ -102,6 +106,7 @@ int main(int argc, char **argv)
FILE *inFile, *outFile;
PLOptState *optstate;
PLOptStatus status;
char *suffix = NULL;
inFile = 0;
outFile = 0;
@ -111,7 +116,7 @@ int main(int argc, char **argv)
progName = progName ? progName+1 : argv[0];
/* Parse command line arguments */
optstate = PL_CreateOptState(argc, argv, "i:o:");
optstate = PL_CreateOptState(argc, argv, "i:o:w:");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
default:
@ -135,6 +140,13 @@ int main(int argc, char **argv)
return -1;
}
break;
case 'w':
if (!strcmp(optstate->value, "c"))
suffix = strdup("CERTIFICATE");
else
suffix = strdup(optstate->value);
break;
}
}
if (status == PL_OPT_BAD)
@ -171,11 +183,17 @@ int main(int argc, char **argv)
#endif
outFile = stdout;
}
if (suffix) {
fprintf(outFile, "-----BEGIN %s-----\n", suffix);
}
rv = encode_file(outFile, inFile);
if (rv != SECSuccess) {
fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
progName, PORT_GetError(), errno);
return -1;
}
if (suffix) {
fprintf(outFile, "-----END %s-----\n", suffix);
}
return 0;
}

View File

@ -27,6 +27,8 @@
#include "xconst.h"
#include "prprf.h"
#include "certutil.h"
#include "genname.h"
#include "prnetdb.h"
#define GEN_BREAK(e) rv=e; break;
@ -665,53 +667,213 @@ AddNscpCertType (void *extHandle, const char *userSuppliedValue)
}
SECStatus
GetOidFromString(PLArenaPool *arena, SECItem *to,
const char *from, size_t fromLen)
{
SECStatus rv;
SECOidTag tag;
SECOidData *coid;
/* try dotted form first */
rv = SEC_StringToOID(arena, to, from, fromLen);
if (rv == SECSuccess) {
return rv;
}
/* Check to see if it matches a name in our oid table.
* SECOID_FindOIDByTag returns NULL if tag is out of bounds.
*/
tag = SEC_OID_UNKNOWN;
coid = SECOID_FindOIDByTag(tag);
for ( ; coid; coid = SECOID_FindOIDByTag(++tag)) {
if (PORT_Strncasecmp(from, coid->desc, fromLen) == 0) {
break;
}
}
if (coid == NULL) {
/* none found */
return SECFailure;
}
return SECITEM_CopyItem(arena, to, &coid->oid);
}
static SECStatus
AddSubjectAltNames(PLArenaPool *arena, CERTGeneralName **existingListp,
const char *names, CERTGeneralNameType type)
const char *constNames, CERTGeneralNameType type)
{
CERTGeneralName *nameList = NULL;
CERTGeneralName *current = NULL;
PRCList *prev = NULL;
const char *cp;
char *tbuf;
char *cp, *nextName = NULL;
SECStatus rv = SECSuccess;
PRBool readTypeFromName = (PRBool) (type == 0);
char *names = NULL;
if (constNames)
names = PORT_Strdup(constNames);
if (names == NULL) {
return SECFailure;
}
/*
* walk down the comma separated list of names. NOTE: there is
* no sanity checks to see if the email address look like
* email addresses.
*
* Each name may optionally be prefixed with a type: string.
* If it isn't, the type from the previous name will be used.
* If there wasn't a previous name yet, the type given
* as a parameter to this function will be used.
* If the type value is zero (undefined), we'll fail.
*/
for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
for (cp=names; cp; cp=nextName) {
int len;
char *end;
char *oidString;
char *nextComma;
CERTName *name;
PRStatus status;
unsigned char *data;
PRNetAddr addr;
nextName = NULL;
if (*cp == ',') {
cp++;
}
end = PORT_Strchr(cp,',');
len = end ? end-cp : PORT_Strlen(cp);
if (len <= 0) {
nextComma = PORT_Strchr(cp, ',');
if (nextComma) {
*nextComma = 0;
nextName = nextComma+1;
}
if ((*cp) == 0) {
continue;
}
tbuf = PORT_ArenaAlloc(arena,len+1);
PORT_Memcpy(tbuf,cp,len);
tbuf[len] = 0;
current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
if (readTypeFromName) {
char *save=cp;
/* Because we already replaced nextComma with end-of-string,
* a found colon belongs to the current name */
cp = PORT_Strchr(cp, ':');
if (cp) {
*cp = 0;
cp++;
type = CERT_GetGeneralNameTypeFromString(save);
if (*cp == 0) {
continue;
}
} else {
if (type == 0) {
/* no type known yet */
rv = SECFailure;
break;
}
cp = save;
}
}
current = PORT_ArenaZNew(arena, CERTGeneralName);
if (!current) {
rv = SECFailure;
break;
}
current->type = type;
switch (type) {
/* string types */
case certRFC822Name:
case certDNSName:
case certURI:
current->name.other.data =
(unsigned char *) PORT_ArenaStrdup(arena,cp);
current->name.other.len = PORT_Strlen(cp);
break;
/* unformated data types */
case certX400Address:
case certEDIPartyName:
/* turn a string into a data and len */
rv = SECFailure; /* punt on these for now */
fprintf(stderr,"EDI Party Name and X.400 Address not supported\n");
break;
case certDirectoryName:
/* certDirectoryName */
name = CERT_AsciiToName(cp);
if (name == NULL) {
rv = SECFailure;
fprintf(stderr, "Invalid Directory Name (\"%s\")\n", cp);
break;
}
rv = CERT_CopyName(arena,&current->name.directoryName,name);
CERT_DestroyName(name);
break;
/* types that require more processing */
case certIPAddress:
/* convert the string to an ip address */
status = PR_StringToNetAddr(cp, &addr);
if (status != PR_SUCCESS) {
rv = SECFailure;
fprintf(stderr, "Invalid IP Address (\"%s\")\n", cp);
break;
}
if (PR_NetAddrFamily(&addr) == PR_AF_INET) {
len = sizeof(addr.inet.ip);
data = (unsigned char *)&addr.inet.ip;
} else if (PR_NetAddrFamily(&addr) == PR_AF_INET6) {
len = sizeof(addr.ipv6.ip);
data = (unsigned char *)&addr.ipv6.ip;
} else {
fprintf(stderr, "Invalid IP Family\n");
rv = SECFailure;
break;
}
current->name.other.data = PORT_ArenaAlloc(arena, len);
if (current->name.other.data == NULL) {
rv = SECFailure;
break;
}
current->name.other.len = len;
PORT_Memcpy(current->name.other.data,data, len);
break;
case certRegisterID:
rv = GetOidFromString(arena, &current->name.other, cp, strlen(cp));
break;
case certOtherName:
oidString = cp;
cp = PORT_Strchr(cp,';');
if (cp == NULL) {
rv = SECFailure;
fprintf(stderr, "missing name in other name\n");
break;
}
*cp++ = 0;
current->name.OthName.name.data =
(unsigned char *) PORT_ArenaStrdup(arena,cp);
if (current->name.OthName.name.data == NULL) {
rv = SECFailure;
break;
}
current->name.OthName.name.len = PORT_Strlen(cp);
rv = GetOidFromString(arena, &current->name.OthName.oid,
oidString, strlen(oidString));
break;
default:
rv = SECFailure;
fprintf(stderr, "Missing or invalid Subject Alternate Name type\n");
break;
}
if (rv == SECFailure) {
break;
}
if (prev) {
current->l.prev = prev;
prev->next = &(current->l);
} else {
nameList = current;
}
current->type = type;
current->name.other.data = (unsigned char *)tbuf;
current->name.other.len = PORT_Strlen(tbuf);
prev = &(current->l);
}
PORT_Free(names);
/* at this point nameList points to the head of a doubly linked,
* but not yet circular, list and current points to its tail. */
if (rv == SECSuccess && nameList) {
@ -749,6 +911,12 @@ AddDNSSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
}
static SECStatus
AddGeneralSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
const char *altNames)
{
return AddSubjectAltNames(arena, existingListp, altNames, 0);
}
static SECStatus
AddBasicConstraint(void *extHandle)
@ -1746,12 +1914,73 @@ AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
return (rv);
}
/* Example of valid input:
* 1.2.3.4:critical:/tmp/abc,5.6.7.8:not-critical:/tmp/xyz
*/
static SECStatus
parseNextGenericExt(const char *nextExtension, const char **oid, int *oidLen,
const char **crit, int *critLen,
const char **filename, int *filenameLen,
const char **next)
{
const char *nextColon;
const char *nextComma;
const char *iter = nextExtension;
if (!iter || !*iter)
return SECFailure;
/* Require colons at earlier positions than nextComma (or end of string ) */
nextComma = strchr(iter, ',');
*oid = iter;
nextColon = strchr(iter, ':');
if (!nextColon || (nextComma && nextColon > nextComma))
return SECFailure;
*oidLen = (nextColon - *oid);
if (!*oidLen)
return SECFailure;
iter = nextColon;
++iter;
*crit = iter;
nextColon = strchr(iter, ':');
if (!nextColon || (nextComma && nextColon > nextComma))
return SECFailure;
*critLen = (nextColon - *crit);
if (!*critLen)
return SECFailure;
iter = nextColon;
++iter;
*filename = iter;
if (nextComma) {
*filenameLen = (nextComma - *filename);
iter = nextComma;
++iter;
*next = iter;
} else {
*filenameLen = strlen(*filename);
*next = NULL;
}
if (!*filenameLen)
return SECFailure;
return SECSuccess;
}
SECStatus
AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
certutilExtnList extList)
certutilExtnList extList, const char *extGeneric)
{
SECStatus rv = SECSuccess;
char *errstring = NULL;
const char *nextExtension = NULL;
do {
/* Add key usage extension */
@ -1864,7 +2093,7 @@ AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
}
}
if (emailAddrs || dnsNames) {
if (emailAddrs || dnsNames || extList[ext_subjectAltName].activated) {
PLArenaPool *arena;
CERTGeneralName *namelist = NULL;
SECItem item = { 0, NULL, 0 };
@ -1874,10 +2103,21 @@ AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
rv = SECFailure;
break;
}
rv = SECSuccess;
rv = AddEmailSubjectAlt(arena, &namelist, emailAddrs);
if (emailAddrs) {
rv |= AddEmailSubjectAlt(arena, &namelist, emailAddrs);
}
rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
if (dnsNames) {
rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
}
if (extList[ext_subjectAltName].activated) {
rv |= AddGeneralSubjectAlt(arena, &namelist,
extList[ext_subjectAltName].arg);
}
if (rv == SECSuccess) {
rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
@ -1898,5 +2138,71 @@ AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
if (rv != SECSuccess) {
SECU_PrintError(progName, "Problem creating %s extension", errstring);
}
nextExtension = extGeneric;
while (nextExtension && *nextExtension) {
SECItem oid_item, value;
PRBool isCritical;
const char *oid, *crit, *filename, *next;
int oidLen, critLen, filenameLen;
PRFileDesc *inFile = NULL;
char *zeroTerminatedFilename = NULL;
rv = parseNextGenericExt(nextExtension, &oid, &oidLen, &crit, &critLen,
&filename, &filenameLen, &next);
if (rv!= SECSuccess) {
SECU_PrintError(progName,
"error parsing generic extension parameter %s",
nextExtension);
break;
}
oid_item.data = NULL;
oid_item.len = 0;
rv = GetOidFromString(NULL, &oid_item, oid, oidLen);
if (rv != SECSuccess) {
SECU_PrintError(progName, "malformed extension OID %s", nextExtension);
break;
}
if (!strncmp("critical", crit, critLen)) {
isCritical = PR_TRUE;
} else if (!strncmp("not-critical", crit, critLen)) {
isCritical = PR_FALSE;
} else {
rv = SECFailure;
SECU_PrintError(progName, "expected 'critical' or 'not-critical'");
break;
}
zeroTerminatedFilename = PL_strndup(filename, filenameLen);
if (!zeroTerminatedFilename) {
rv = SECFailure;
SECU_PrintError(progName, "out of memory");
break;
}
rv = SECFailure;
inFile = PR_Open(zeroTerminatedFilename, PR_RDONLY, 0);
if (inFile) {
rv = SECU_ReadDERFromFile(&value, inFile, PR_FALSE, PR_FALSE);
PR_Close(inFile);
inFile = NULL;
}
if (rv != SECSuccess) {
SECU_PrintError(progName, "unable to read file %s",
zeroTerminatedFilename);
}
PL_strfree(zeroTerminatedFilename);
if (rv != SECSuccess) {
break;
}
rv = CERT_AddExtensionByOID(extHandle, &oid_item, &value, isCritical,
PR_FALSE /*copyData*/);
if (rv != SECSuccess) {
SECITEM_FreeItem(&oid_item, PR_FALSE);
SECITEM_FreeItem(&value, PR_FALSE);
SECU_PrintError(progName, "failed to add extension %s", nextExtension);
break;
}
nextExtension = next;
}
return rv;
}

View File

@ -182,7 +182,7 @@ static SECStatus
CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii,
const char *emailAddrs, const char *dnsNames,
certutilExtnList extnList,
certutilExtnList extnList, const char *extGeneric,
/*out*/ SECItem *result)
{
CERTSubjectPublicKeyInfo *spki;
@ -220,7 +220,7 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
PORT_FreeArena (arena, PR_FALSE);
return SECFailure;
}
if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList)
if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric)
!= SECSuccess) {
PORT_FreeArena (arena, PR_FALSE);
return SECFailure;
@ -420,11 +420,64 @@ DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii)
}
static SECStatus
listCerts(CERTCertDBHandle *handle, char *name, char *email, PK11SlotInfo *slot,
PRBool raw, PRBool ascii, PRFileDesc *outfile, void *pwarg)
outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
SECItem *extensionOID, PRFileDesc *outfile)
{
SECItem data;
PRInt32 numBytes;
SECStatus rv = SECFailure;
if (extensionOID) {
int i;
PRBool found = PR_FALSE;
for (i=0; the_cert->extensions[i] != NULL; i++) {
CERTCertExtension *extension = the_cert->extensions[i];
if (SECITEM_CompareItem(&extension->id, extensionOID) == SECEqual) {
found = PR_TRUE;
numBytes = PR_Write(outfile, extension->value.data,
extension->value.len);
rv = SECSuccess;
if (numBytes != (PRInt32) extension->value.len) {
SECU_PrintSystemError(progName, "error writing extension");
rv = SECFailure;
}
rv = SECSuccess;
break;
}
}
if (!found) {
SECU_PrintSystemError(progName, "extension not found");
rv = SECFailure;
}
} else {
data.data = the_cert->derCert.data;
data.len = the_cert->derCert.len;
if (ascii) {
PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
rv = SECSuccess;
} else if (raw) {
numBytes = PR_Write(outfile, data.data, data.len);
rv = SECSuccess;
if (numBytes != (PRInt32) data.len) {
SECU_PrintSystemError(progName, "error writing raw cert");
rv = SECFailure;
}
} else {
rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
if (rv != SECSuccess) {
SECU_PrintError(progName, "problem printing certificate");
}
}
}
return rv;
}
static SECStatus
listCerts(CERTCertDBHandle *handle, char *name, char *email,
PK11SlotInfo *slot, PRBool raw, PRBool ascii,
SECItem *extensionOID,
PRFileDesc *outfile, void *pwarg)
{
SECStatus rv = SECFailure;
CERTCertList *certs;
CERTCertListNode *node;
@ -461,34 +514,13 @@ listCerts(CERTCertDBHandle *handle, char *name, char *email, PK11SlotInfo *slot,
}
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
node = CERT_LIST_NEXT(node)) {
the_cert = node->cert;
/* now get the subjectList that matches this cert */
data.data = the_cert->derCert.data;
data.len = the_cert->derCert.len;
if (ascii) {
PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
rv = SECSuccess;
} else if (raw) {
numBytes = PR_Write(outfile, data.data, data.len);
if (numBytes != (PRInt32) data.len) {
SECU_PrintSystemError(progName, "error writing raw cert");
rv = SECFailure;
}
rv = SECSuccess;
} else {
rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
if (rv != SECSuccess) {
SECU_PrintError(progName, "problem printing certificate");
}
}
rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
outfile);
if (rv != SECSuccess) {
break;
}
}
} else if (email) {
CERTCertificate *the_cert;
certs = PK11_FindCertsFromEmailAddress(email, NULL);
if (!certs) {
SECU_PrintError(progName,
@ -498,28 +530,8 @@ listCerts(CERTCertDBHandle *handle, char *name, char *email, PK11SlotInfo *slot,
}
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
node = CERT_LIST_NEXT(node)) {
the_cert = node->cert;
/* now get the subjectList that matches this cert */
data.data = the_cert->derCert.data;
data.len = the_cert->derCert.len;
if (ascii) {
PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
BTOA_DataToAscii(data.data, data.len),
NS_CERT_TRAILER);
rv = SECSuccess;
} else if (raw) {
numBytes = PR_Write(outfile, data.data, data.len);
rv = SECSuccess;
if (numBytes != (PRInt32) data.len) {
SECU_PrintSystemError(progName, "error writing raw cert");
rv = SECFailure;
}
} else {
rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
if (rv != SECSuccess) {
SECU_PrintError(progName, "problem printing certificate");
}
}
rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
outfile);
if (rv != SECSuccess) {
break;
}
@ -547,8 +559,9 @@ listCerts(CERTCertDBHandle *handle, char *name, char *email, PK11SlotInfo *slot,
static SECStatus
ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
PK11SlotInfo *slot, PRBool raw, PRBool ascii, PRFileDesc *outfile,
secuPWData *pwdata)
PK11SlotInfo *slot, PRBool raw, PRBool ascii,
SECItem *extensionOID,
PRFileDesc *outfile, secuPWData *pwdata)
{
SECStatus rv;
@ -569,7 +582,8 @@ ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
CERT_DestroyCertList(list);
return SECSuccess;
}
rv = listCerts(handle, nickname, email, slot, raw, ascii, outfile, pwdata);
rv = listCerts(handle, nickname, email, slot, raw, ascii,
extensionOID, outfile, pwdata);
return rv;
}
@ -615,6 +629,15 @@ ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
case 'O':
usage = certificateUsageStatusResponder;
break;
case 'L':
usage = certificateUsageSSLCA;
break;
case 'A':
usage = certificateUsageAnyCA;
break;
case 'Y':
usage = certificateUsageVerifyCA;
break;
case 'C':
usage = certificateUsageSSLClient;
break;
@ -989,7 +1012,7 @@ PrintSyntax(char *progName)
FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
FPS "\t%s -L [-n cert-name] [--email email-address] [-X] [-r] [-a]\n",
progName);
FPS "\t\t [-d certdir] [-P dbprefix]\n");
FPS "\t\t [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
progName);
FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName);
@ -1008,7 +1031,8 @@ PrintSyntax(char *progName)
"\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
"\t\t [-8 DNS-names]\n"
"\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
"\t\t [--extSKID] [--extNC]\n", progName);
"\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
"\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
exit(1);
}
@ -1308,7 +1332,7 @@ static void luL(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "L"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s List all certs, or print out a single named cert\n",
FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
"-L");
if (ul == usage_selected && !is_my_command)
return;
@ -1327,6 +1351,9 @@ static void luL(enum usage_level ul, const char *command)
" -r");
FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
" -a");
FPS "%-20s \n"
"%-20s For single cert, print binary DER encoding of extension OID\n",
" --dump-ext-val OID", "");
FPS "\n");
}
@ -1472,6 +1499,9 @@ static void luV(enum usage_level ul, const char *command)
FPS "%-20s Specify certificate usage:\n", " -u certusage");
FPS "%-25s C \t SSL Client\n", "");
FPS "%-25s V \t SSL Server\n", "");
FPS "%-25s L \t SSL CA\n", "");
FPS "%-25s A \t Any CA\n", "");
FPS "%-25s Y \t Verify CA\n", "");
FPS "%-25s S \t Email signer\n", "");
FPS "%-25s R \t Email Recipient\n", "");
FPS "%-25s O \t OCSP status responder\n", "");
@ -1638,6 +1668,18 @@ static void luS(enum usage_level ul, const char *command)
" See -G for available key flag options");
FPS "%-20s Create a name constraints extension\n",
" --extNC ");
FPS "%-20s \n"
"%-20s Create a Subject Alt Name extension with one or multiple names\n",
" --extSAN type:name[,type:name]...", "");
FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", "");
FPS "%-20s \n"
"%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
"%-20s by loading their encodings from external files.\n",
" --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
FPS "%-20s - OID (example): 1.2.3.4\n", "");
FPS "%-20s - critical-flag: critical or not-critical\n", "");
FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
FPS "\n");
}
@ -1836,6 +1878,7 @@ CreateCert(
PRBool ascii,
PRBool selfsign,
certutilExtnList extnList,
const char *extGeneric,
int certVersion,
SECItem * certDER)
{
@ -1864,7 +1907,7 @@ CreateCert(
GEN_BREAK (SECFailure)
}
rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList);
rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
if (rv != SECSuccess) {
GEN_BREAK (SECFailure)
}
@ -2212,6 +2255,9 @@ enum certutilOpts {
opt_KeyAttrFlags,
opt_EmptyPassword,
opt_CertVersion,
opt_AddSubjectAltNameExt,
opt_DumpExtensionValue,
opt_GenericExtensions,
opt_Help
};
@ -2323,6 +2369,11 @@ secuCommandFlag options_init[] =
"empty-password"},
{ /* opt_CertVersion */ 0, PR_FALSE, 0, PR_FALSE,
"certVersion"},
{ /* opt_AddSubjectAltExt */ 0, PR_TRUE, 0, PR_FALSE, "extSAN"},
{ /* opt_DumpExtensionValue */ 0, PR_TRUE, 0, PR_FALSE,
"dump-ext-val"},
{ /* opt_GenericExtensions */ 0, PR_TRUE, 0, PR_FALSE,
"extGeneric"},
};
#define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0]))
@ -2663,9 +2714,10 @@ certutil_main(int argc, char **argv, PRBool initialize)
return 255;
}
/* if -L is given raw or ascii mode, it must be for only one cert. */
/* if -L is given raw, ascii or dump mode, it must be for only one cert. */
if (certutil.commands[cmd_ListCerts].activated &&
(certutil.options[opt_ASCIIForIO].activated ||
certutil.options[opt_DumpExtensionValue].activated ||
certutil.options[opt_BinaryDER].activated) &&
!certutil.options[opt_Nickname].activated) {
PR_fprintf(PR_STDERR,
@ -2985,10 +3037,29 @@ merge_fail:
/* List certs (-L) */
if (certutil.commands[cmd_ListCerts].activated) {
rv = ListCerts(certHandle, name, email, slot,
certutil.options[opt_BinaryDER].activated,
certutil.options[opt_ASCIIForIO].activated,
outFile, &pwdata);
if (certutil.options[opt_DumpExtensionValue].activated) {
const char *oid_str;
SECItem oid_item;
SECStatus srv;
oid_item.data = NULL;
oid_item.len = 0;
oid_str = certutil.options[opt_DumpExtensionValue].arg;
srv = GetOidFromString(NULL, &oid_item, oid_str, strlen(oid_str));
if (srv != SECSuccess) {
SECU_PrintError(progName, "malformed extension OID %s",
oid_str);
goto shutdown;
}
rv = ListCerts(certHandle, name, email, slot,
PR_TRUE /*binary*/, PR_FALSE /*ascii*/,
&oid_item,
outFile, &pwdata);
} else {
rv = ListCerts(certHandle, name, email, slot,
certutil.options[opt_BinaryDER].activated,
certutil.options[opt_ASCIIForIO].activated,
NULL, outFile, &pwdata);
}
goto shutdown;
}
if (certutil.commands[cmd_DumpChain].activated) {
@ -3179,6 +3250,12 @@ merge_fail:
certutil_extns[ext_extKeyUsage].arg =
certutil.options[opt_AddCmdExtKeyUsageExt].arg;
}
certutil_extns[ext_subjectAltName].activated =
certutil.options[opt_AddSubjectAltNameExt].activated;
if (certutil_extns[ext_subjectAltName].activated) {
certutil_extns[ext_subjectAltName].arg =
certutil.options[opt_AddSubjectAltNameExt].arg;
}
certutil_extns[ext_authInfoAcc].activated =
certutil.options[opt_AddAuthInfoAccExt].activated;
@ -3218,6 +3295,8 @@ merge_fail:
certutil.options[opt_ExtendedEmailAddrs].arg,
certutil.options[opt_ExtendedDNSNames].arg,
certutil_extns,
(certutil.options[opt_GenericExtensions].activated ?
certutil.options[opt_GenericExtensions].arg : NULL),
&certReqDER);
if (rv)
goto shutdown;
@ -3240,6 +3319,8 @@ merge_fail:
NULL,
NULL,
nullextnlist,
(certutil.options[opt_GenericExtensions].activated ?
certutil.options[opt_GenericExtensions].arg : NULL),
&certReqDER);
if (rv)
goto shutdown;
@ -3259,6 +3340,8 @@ merge_fail:
certutil.commands[cmd_CreateNewCert].activated,
certutil.options[opt_SelfSign].activated,
certutil_extns,
(certutil.options[opt_GenericExtensions].activated ?
certutil.options[opt_GenericExtensions].arg : NULL),
certVersion,
&certDER);
if (rv)

View File

@ -35,6 +35,7 @@ enum certutilExtns {
ext_inhibitAnyPolicy,
ext_subjectKeyID,
ext_nameConstraints,
ext_subjectAltName,
ext_End
};
@ -47,7 +48,11 @@ typedef ExtensionEntry certutilExtnList[ext_End];
extern SECStatus
AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
certutilExtnList extList);
certutilExtnList extList, const char *extGeneric);
extern SECStatus
GetOidFromString(PLArenaPool *arena, SECItem *to,
const char *from, size_t fromLen);
#endif /* _CERTUTIL_H */

View File

@ -1312,8 +1312,10 @@ main(int argc, char **argv)
inFile = PR_Open(revoInfo->crlFilename, PR_RDONLY, 0);
if (inFile) {
rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
PR_Close(inFile);
inFile = NULL;
}
if (!inFile || rv != SECSuccess) {
if (rv != SECSuccess) {
fprintf(stderr, "unable to read crl file %s\n",
revoInfo->crlFilename);
exit(1);

View File

@ -52,6 +52,19 @@ static char consoleName[] = {
#include "ssl.h"
#include "sslproto.h"
static PRBool utf8DisplayEnabled = PR_FALSE;
void
SECU_EnableUtf8Display(PRBool enable)
{
utf8DisplayEnabled = enable;
}
PRBool
SECU_GetUtf8DisplayEnabled(void)
{
return utf8DisplayEnabled;
}
static void
secu_ClearPassword(char *p)
@ -609,12 +622,22 @@ secu_PrintRawStringQuotesOptional(FILE *out, SECItem *si, const char *m,
for (i = 0; i < si->len; i++) {
unsigned char val = si->data[i];
unsigned char c;
if (SECU_GetWrapEnabled() && column > 76) {
SECU_Newline(out);
SECU_Indent(out, level); column = level*INDENT_MULT;
}
fprintf(out,"%c", printable[val]); column++;
if (utf8DisplayEnabled) {
if (val < 32)
c = '.';
else
c = val;
} else {
c = printable[val];
}
fprintf(out,"%c", c);
column++;
}
if (quotes) {
@ -2441,19 +2464,19 @@ loser:
int
SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
{
unsigned char fingerprint[20];
unsigned char fingerprint[SHA256_LENGTH];
char *fpStr = NULL;
int err = PORT_GetError();
SECStatus rv;
SECItem fpItem;
/* print MD5 fingerprint */
/* Print SHA-256 fingerprint */
memset(fingerprint, 0, sizeof fingerprint);
rv = PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
fpItem.data = fingerprint;
fpItem.len = MD5_LENGTH;
fpItem.len = SHA256_LENGTH;
fpStr = CERT_Hexify(&fpItem, 1);
SECU_Indent(out, level); fprintf(out, "%s (MD5):", m);
SECU_Indent(out, level); fprintf(out, "%s (SHA-256):", m);
if (SECU_GetWrapEnabled()) {
fprintf(out, "\n");
SECU_Indent(out, level+1);

View File

@ -139,6 +139,9 @@ SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
extern PRBool SECU_GetWrapEnabled(void);
extern void SECU_EnableWrap(PRBool enable);
extern PRBool SECU_GetUtf8DisplayEnabled(void);
extern void SECU_EnableUtf8Display(PRBool enable);
/* revalidate the cert and print information about cert verification
* failure at time == now */
extern void

View File

@ -22,22 +22,27 @@ extern int fprintf(FILE *, char *, ...);
static void Usage(char *progName)
{
fprintf(stderr,
"Usage: %s -t type [-a] [-i input] [-o output] [-w]\n",
"Usage: %s [-t type] [-a] [-i input] [-o output] [-w] [-u]\n",
progName);
fprintf(stderr, "%-20s Specify the input type (must be one of %s,\n",
fprintf(stderr, "Pretty prints a file containing ASN.1 data in DER or ascii format.\n");
fprintf(stderr, "%-14s Specify input and display type: %s (sk),\n",
"-t type", SEC_CT_PRIVATE_KEY);
fprintf(stderr, "%-20s %s, %s, %s,\n", "", SEC_CT_PUBLIC_KEY,
fprintf(stderr, "%-14s %s (pk), %s (c), %s (cr),\n", "", SEC_CT_PUBLIC_KEY,
SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
fprintf(stderr, "%-20s %s, %s, %s or %s)\n", "", SEC_CT_CERTIFICATE_ID,
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, "%-20s Input is in ascii encoded form (RFC1113)\n",
fprintf(stderr, "%-14s (Use either the long type name or the shortcut.)\n", "", SEC_CT_CERTIFICATE_ID,
SEC_CT_PKCS7, SEC_CT_CRL, SEC_CT_NAME);
fprintf(stderr, "%-14s Input is in ascii encoded form (RFC1113)\n",
"-a");
fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
fprintf(stderr, "%-14s Define an input file to use (default is stdin)\n",
"-i input");
fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
fprintf(stderr, "%-14s Define an output file to use (default is stdout)\n",
"-o output");
fprintf(stderr, "%-20s Don't wrap long output lines\n",
fprintf(stderr, "%-14s Don't wrap long output lines\n",
"-w");
fprintf(stderr, "%-14s Use UTF-8 (default is to show non-ascii as .)\n",
"-u");
exit(-1);
}
@ -59,7 +64,7 @@ int main(int argc, char **argv)
inFile = 0;
outFile = 0;
typeTag = 0;
optstate = PL_CreateOptState(argc, argv, "at:i:o:w");
optstate = PL_CreateOptState(argc, argv, "at:i:o:uw");
while ( PL_GetNextOpt(optstate) == PL_OPT_OK ) {
switch (optstate->option) {
case '?':
@ -92,6 +97,10 @@ int main(int argc, char **argv)
typeTag = strdup(optstate->value);
break;
case 'u':
SECU_EnableUtf8Display(PR_TRUE);
break;
case 'w':
wrap = PR_FALSE;
break;
@ -125,27 +134,34 @@ int main(int argc, char **argv)
SECU_EnableWrap(wrap);
/* Pretty print it */
if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0) {
if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0 ||
PORT_Strcmp(typeTag, "c") == 0) {
rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
SECU_PrintCertificate);
} else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0) {
} else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0 ||
PORT_Strcmp(typeTag, "ci") == 0) {
rv = SECU_PrintSignedContent(outFile, &data, 0, 0,
SECU_PrintDumpDerIssuerAndSerial);
} else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0) {
} else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0 ||
PORT_Strcmp(typeTag, "cr") == 0) {
rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
SECU_PrintCertificateRequest);
} else if (PORT_Strcmp (typeTag, SEC_CT_CRL) == 0) {
} 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) {
} 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) {
} else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0 ||
PORT_Strcmp (typeTag, "pk") == 0) {
rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0);
} else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0) {
} else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0 ||
PORT_Strcmp (typeTag, "p7") == 0) {
rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
"PKCS #7 Content Info", 0);
} else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0) {
} else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0 ||
PORT_Strcmp (typeTag, "n") == 0) {
rv = SECU_PrintDERName(outFile, &data, "Name", 0);
} else {
fprintf(stderr, "%s: don't know how to print out '%s' files\n",

View File

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

View File

@ -28,12 +28,12 @@ static const NameToKind name2kinds[] = {
* (See: http://www.iana.org/assignments/ldap-parameters)
*/
/* RFC 3280, 4630 MUST SUPPORT */
{ "CN", 64, SEC_OID_AVA_COMMON_NAME, SEC_ASN1_DS},
{ "CN", 640, SEC_OID_AVA_COMMON_NAME, SEC_ASN1_DS},
{ "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE,
SEC_ASN1_DS},
{ "O", 64, SEC_OID_AVA_ORGANIZATION_NAME,
{ "O", 128, SEC_OID_AVA_ORGANIZATION_NAME,
SEC_ASN1_DS},
{ "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
{ "OU", 128, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
SEC_ASN1_DS},
{ "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER, SEC_ASN1_PRINTABLE_STRING},
{ "C", 2, SEC_OID_AVA_COUNTRY_NAME, SEC_ASN1_PRINTABLE_STRING},
@ -377,7 +377,7 @@ ParseRFC1485AVA(PLArenaPool *arena, const char **pbp, const char *endptr)
char sep = 0;
char tagBuf[32];
char valBuf[384];
char valBuf[1024];
PORT_Assert(arena);
if (SECSuccess != scanTag(pbp, endptr, tagBuf, sizeof tagBuf) ||
@ -889,7 +889,7 @@ get_hex_string(SECItem *data)
static SECStatus
AppendAVA(stringBuf *bufp, CERTAVA *ava, CertStrictnessLevel strict)
{
#define TMPBUF_LEN 384
#define TMPBUF_LEN 2048
const NameToKind *pn2k = name2kinds;
SECItem *avaValue = NULL;
char *unknownTag = NULL;

View File

@ -137,6 +137,39 @@ const SEC_ASN1Template CERT_GeneralNamesTemplate[] = {
};
static struct {
CERTGeneralNameType type;
char *name;
} typesArray[] = {
{ certOtherName, "other" },
{ certRFC822Name, "email" },
{ certRFC822Name, "rfc822" },
{ certDNSName, "dns" },
{ certX400Address, "x400" },
{ certX400Address, "x400addr" },
{ certDirectoryName, "directory" },
{ certDirectoryName, "dn" },
{ certEDIPartyName, "edi" },
{ certEDIPartyName, "ediparty" },
{ certURI, "uri" },
{ certIPAddress, "ip" },
{ certIPAddress, "ipaddr" },
{ certRegisterID, "registerid" }
};
CERTGeneralNameType
CERT_GetGeneralNameTypeFromString(const char *string)
{
int types_count = sizeof(typesArray)/sizeof(typesArray[0]);
int i;
for (i=0; i < types_count; i++) {
if (PORT_Strcasecmp(string, typesArray[i].name) == 0) {
return typesArray[i].type;
}
}
return 0;
}
CERTGeneralName *
CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type)

View File

@ -26,6 +26,9 @@ cert_DecodeGeneralNames(PLArenaPool *arena, SECItem **encodedGenName);
extern SECStatus
cert_DestroyGeneralNames(CERTGeneralName *name);
extern CERTGeneralNameType
CERT_GetGeneralNameTypeFromString(const char *string);
extern SECStatus
cert_EncodeNameConstraints(CERTNameConstraints *constraints, PLArenaPool *arena,
SECItem *dest);

View File

@ -56,7 +56,7 @@ extern SECItem *DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len);
/*
** Create a new signature context used for signing a data stream.
** "alg" the signature algorithm to use (e.g. SEC_OID_RSA_WITH_MD5)
** "alg" the signature algorithm to use (e.g. SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION)
** "privKey" the private key to use
*/
extern SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *privKey);

View File

@ -37,7 +37,7 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
* PKCS #7 algTag if we were just going to change here you might
* ask. Well the answer is for some cards we may have to do the
* hashing on card. It may not support CKM_RSA_PKCS sign algorithm,
* it may just support CKM_RSA_PKCS_WITH_SHA1 and/or CKM_RSA_PKCS_WITH_MD5.
* it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS.
*/
/* we have a private key, not a public key, so don't pass it in */
rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg);

View File

@ -1406,6 +1406,17 @@ RSA_PrivateKeyCheck(RSAPrivateKey *key)
CHECK_MPI_OK( mp_init(&d_q) );
CHECK_MPI_OK( mp_init(&qInv) );
CHECK_MPI_OK( mp_init(&res) );
if (!key->modulus.data || !key->prime1.data || !key->prime2.data ||
!key->publicExponent.data || !key->privateExponent.data ||
!key->exponent1.data || !key->exponent2.data ||
!key->coefficient.data) {
/*call RSA_PopulatePrivateKey first, if the application wishes to
* recover these parameters */
err = MP_BADARG;
goto cleanup;
}
SECITEM_TO_MPINT(key->modulus, &n);
SECITEM_TO_MPINT(key->prime1, &p);
SECITEM_TO_MPINT(key->prime2, &q);
@ -1458,27 +1469,19 @@ RSA_PrivateKeyCheck(RSAPrivateKey *key)
CHECK_MPI_OK( mp_mulmod(&d, &e, &qsub1, &res) );
VERIFY_MPI_EQUAL_1(&res);
/*
* The following errors can be recovered from.
* The following errors can be recovered from. However, the purpose of this
* function is to check consistency, so they are not.
*/
/* d_p == d mod p-1 */
CHECK_MPI_OK( mp_mod(&d, &psub1, &res) );
if (mp_cmp(&d_p, &res) != 0) {
/* swap in the correct value */
CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent1) );
}
VERIFY_MPI_EQUAL(&res, &d_p);
/* d_q == d mod q-1 */
CHECK_MPI_OK( mp_mod(&d, &qsub1, &res) );
if (mp_cmp(&d_q, &res) != 0) {
/* swap in the correct value */
CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent2) );
}
VERIFY_MPI_EQUAL(&res, &d_q);
/* q * q**-1 == 1 mod p */
CHECK_MPI_OK( mp_mulmod(&q, &qInv, &p, &res) );
if (mp_cmp_d(&res, 1) != 0) {
/* compute the correct value */
CHECK_MPI_OK( mp_invmod(&q, &p, &qInv) );
CHECK_SEC_OK( swap_in_key_value(key->arena, &qInv, &key->coefficient) );
}
VERIFY_MPI_EQUAL_1(&res);
cleanup:
mp_clear(&n);
mp_clear(&p);

View File

@ -1055,6 +1055,8 @@ SECMOD_InternaltoPubMechFlags;
;+};
;+NSS_3.16.2 { # NSS 3.16.2 release
;+ global:
CERT_AddExtensionByOID;
CERT_GetGeneralNameTypeFromString;
PK11_PubEncrypt;
PK11_PrivDecrypt;
;+ local:

View File

@ -981,8 +981,15 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert,
* CERTCertificate, and finish
*/
nssPKIObject_AddInstance(&c->object, certobj);
/* nssTrustDomain_AddCertsToCache may release a reference to 'c' and
* replace 'c' by a different value. So we add a reference to 'c' to
* prevent 'c' from being destroyed. */
nssCertificate_AddRef(c);
nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
/* XXX should we pass the original value of 'c' to
* STAN_ForceCERTCertificateUpdate? */
(void)STAN_ForceCERTCertificateUpdate(c);
nssCertificate_Destroy(c);
SECITEM_FreeItem(keyID,PR_TRUE);
return SECSuccess;
loser:

View File

@ -55,6 +55,11 @@ static const CK_C_INITIALIZE_ARGS secmodLockFunctions = {
CKF_OS_LOCKING_OK
,NULL
};
static const CK_C_INITIALIZE_ARGS secmodNoLockArgs = {
NULL, NULL, NULL, NULL,
CKF_LIBRARY_CANT_CREATE_OS_THREADS
,NULL
};
static PRBool loadSingleThreadedModules = PR_TRUE;
static PRBool enforceAlreadyInitializedError = PR_TRUE;
@ -209,12 +214,18 @@ secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload,
return SECFailure;
}
if (mod->isThreadSafe == PR_FALSE) {
pInitArgs = NULL;
} else if (mod->libraryParams == NULL) {
pInitArgs = (void *) &secmodLockFunctions;
if (mod->libraryParams == NULL) {
if (mod->isThreadSafe) {
pInitArgs = (void *) &secmodLockFunctions;
} else {
pInitArgs = NULL;
}
} else {
moduleArgs = secmodLockFunctions;
if (mod->isThreadSafe) {
moduleArgs = secmodLockFunctions;
} else {
moduleArgs = secmodNoLockArgs;
}
moduleArgs.LibraryParameters = (void *) mod->libraryParams;
pInitArgs = &moduleArgs;
}
@ -251,18 +262,30 @@ secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload,
}
}
if (crv != CKR_OK) {
if (pInitArgs == NULL ||
if (!mod->isThreadSafe ||
crv == CKR_NETSCAPE_CERTDB_FAILED ||
crv == CKR_NETSCAPE_KEYDB_FAILED) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
/* If we had attempted to init a single threaded module "with"
* parameters and it failed, should we retry "without" parameters?
* (currently we don't retry in this scenario) */
if (!loadSingleThreadedModules) {
PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
return SECFailure;
}
/* If we arrive here, the module failed a ThreadSafe init. */
mod->isThreadSafe = PR_FALSE;
crv = PK11_GETTAB(mod)->C_Initialize(NULL);
if (!mod->libraryParams) {
pInitArgs = NULL;
} else {
moduleArgs = secmodNoLockArgs;
moduleArgs.LibraryParameters = (void *) mod->libraryParams;
pInitArgs = &moduleArgs;
}
crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) &&
(!enforceAlreadyInitializedError)) {
*alreadyLoaded = PR_TRUE;

View File

@ -4598,9 +4598,12 @@ nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
}
return (SECSuccess);
loser:
loser:
if (handle->dbMon) {
PZ_DestroyMonitor(handle->dbMon);
handle->dbMon = NULL;
}
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return(SECFailure);
}

View File

@ -989,7 +989,7 @@ static NSSLOWKEYPrivateKey *
sftk_mkPrivKey(SFTKObject *object,CK_KEY_TYPE key, CK_RV *rvp);
static SECStatus
sftk_fillRSAPrivateKey(SFTKObject *object);
sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded);
/*
* check the consistancy and initialize a Private Key Object
@ -1005,12 +1005,14 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
CK_BBOOL derive = CK_TRUE;
CK_BBOOL ckfalse = CK_FALSE;
PRBool createObjectInfo = PR_TRUE;
PRBool fillPrivateKey = PR_FALSE;
int missing_rsa_mod_component = 0;
int missing_rsa_exp_component = 0;
int missing_rsa_crt_component = 0;
SECItem mod;
CK_RV crv;
SECStatus rv;
switch (key_type) {
case CKK_RSA:
@ -1045,19 +1047,19 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
int have_exp = 2- missing_rsa_exp_component;
int have_component = 5-
(missing_rsa_exp_component+missing_rsa_mod_component);
SECStatus rv;
if ((have_exp == 0) || (have_component < 3)) {
/* nope, not enough to reconstruct the private key */
return CKR_TEMPLATE_INCOMPLETE;
}
/*fill in the missing parameters */
rv = sftk_fillRSAPrivateKey(object);
if (rv != SECSuccess) {
return CKR_TEMPLATE_INCOMPLETE;
}
fillPrivateKey = PR_TRUE;
}
/*verify the parameters for consistency*/
rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey);
if (rv != SECSuccess) {
return CKR_TEMPLATE_INCOMPLETE;
}
/* make sure Netscape DB attribute is set correctly */
crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
if (crv != CKR_OK) return crv;
@ -1151,7 +1153,6 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
CK_RV crv;
if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
@ -1942,10 +1943,11 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
}
/*
* we have a partial rsa private key, fill in the rest
* If a partial RSA private key is present, fill in the rest if necessary,
* and then verify the parameters are well-formed
*/
static SECStatus
sftk_fillRSAPrivateKey(SFTKObject *object)
sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded)
{
RSAPrivateKey tmpKey = { 0 };
SFTKAttribute *modulus = NULL;
@ -1953,6 +1955,9 @@ sftk_fillRSAPrivateKey(SFTKObject *object)
SFTKAttribute *prime2 = NULL;
SFTKAttribute *privateExponent = NULL;
SFTKAttribute *publicExponent = NULL;
SFTKAttribute *exponent1 = NULL;
SFTKAttribute *exponent2 = NULL;
SFTKAttribute *coefficient = NULL;
SECStatus rv;
CK_RV crv;
@ -1983,44 +1988,82 @@ sftk_fillRSAPrivateKey(SFTKObject *object)
if (publicExponent) {
tmpKey.publicExponent.data = publicExponent->attrib.pValue;
tmpKey.publicExponent.len = publicExponent->attrib.ulValueLen;
}
}
exponent1 = sftk_FindAttribute(object, CKA_EXPONENT_1);
if (exponent1) {
tmpKey.exponent1.data = exponent1->attrib.pValue;
tmpKey.exponent1.len = exponent1->attrib.ulValueLen;
}
exponent2 = sftk_FindAttribute(object, CKA_EXPONENT_2);
if (exponent2) {
tmpKey.exponent2.data = exponent2->attrib.pValue;
tmpKey.exponent2.len = exponent2->attrib.ulValueLen;
}
coefficient = sftk_FindAttribute(object, CKA_COEFFICIENT);
if (coefficient) {
tmpKey.coefficient.data = coefficient->attrib.pValue;
tmpKey.coefficient.len = coefficient->attrib.ulValueLen;
}
/*
* populate requires one exponent plus 2 other components to work.
* we expected our caller to check that first. If that didn't happen,
* populate will simply return an error here.
*/
rv = RSA_PopulatePrivateKey(&tmpKey);
if (fillIfNeeded) {
/*
* populate requires one exponent plus 2 other components to work.
* we expected our caller to check that first. If that didn't happen,
* populate will simply return an error here.
*/
rv = RSA_PopulatePrivateKey(&tmpKey);
if (rv != SECSuccess) {
goto loser;
}
}
rv = RSA_PrivateKeyCheck(&tmpKey);
if (rv != SECSuccess) {
goto loser;
}
/* now that we have a fully populated key, set all our attribute values */
rv = SECFailure;
crv = sftk_forceAttribute(object,CKA_MODULUS,
sftk_item_expand(&tmpKey.modulus));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_PUBLIC_EXPONENT,
sftk_item_expand(&tmpKey.publicExponent));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_PRIVATE_EXPONENT,
sftk_item_expand(&tmpKey.privateExponent));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_PRIME_1,
sftk_item_expand(&tmpKey.prime1));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_PRIME_2,
sftk_item_expand(&tmpKey.prime2));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_EXPONENT_1,
sftk_item_expand(&tmpKey.exponent1));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_EXPONENT_2,
sftk_item_expand(&tmpKey.exponent2));
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object,CKA_COEFFICIENT,
sftk_item_expand(&tmpKey.coefficient));
if (crv != CKR_OK) goto loser;
if (!modulus || modulus->attrib.pValue != tmpKey.modulus.data) {
crv = sftk_forceAttribute(object,CKA_MODULUS,
sftk_item_expand(&tmpKey.modulus));
if (crv != CKR_OK) goto loser;
}
if (!publicExponent ||
publicExponent->attrib.pValue != tmpKey.publicExponent.data) {
crv = sftk_forceAttribute(object, CKA_PUBLIC_EXPONENT,
sftk_item_expand(&tmpKey.publicExponent));
if (crv != CKR_OK) goto loser;
}
if (!privateExponent ||
privateExponent->attrib.pValue != tmpKey.privateExponent.data) {
crv = sftk_forceAttribute(object, CKA_PRIVATE_EXPONENT,
sftk_item_expand(&tmpKey.privateExponent));
if (crv != CKR_OK) goto loser;
}
if (!prime1 || prime1->attrib.pValue != tmpKey.prime1.data) {
crv = sftk_forceAttribute(object, CKA_PRIME_1,
sftk_item_expand(&tmpKey.prime1));
if (crv != CKR_OK) goto loser;
}
if (!prime2 || prime2->attrib.pValue != tmpKey.prime2.data) {
crv = sftk_forceAttribute(object, CKA_PRIME_2,
sftk_item_expand(&tmpKey.prime2));
if (crv != CKR_OK) goto loser;
}
if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
crv = sftk_forceAttribute(object, CKA_EXPONENT_1,
sftk_item_expand(&tmpKey.exponent1));
if (crv != CKR_OK) goto loser;
}
if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
crv = sftk_forceAttribute(object, CKA_EXPONENT_2,
sftk_item_expand(&tmpKey.exponent2));
if (crv != CKR_OK) goto loser;
}
if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
crv = sftk_forceAttribute(object, CKA_COEFFICIENT,
sftk_item_expand(&tmpKey.coefficient));
if (crv != CKR_OK) goto loser;
}
rv = SECSuccess;
/* we're done (one way or the other), clean up all our stuff */
@ -2046,12 +2089,6 @@ loser:
return rv;
}
/* Generate a low private key structure from an object */
NSSLOWKEYPrivateKey *
sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp)
@ -3130,9 +3167,6 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
if (slot == NULL) return CKR_SLOT_ID_INVALID;
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,
sizeof(pInfo->manufacturerID));
PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,
@ -3159,6 +3193,8 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
/* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR;
pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR;
pInfo->firmwareVersion.major = SOFTOKEN_VPATCH;
pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD;
return CKR_OK;
}

View File

@ -412,3 +412,9 @@ ER3(SSL_ERROR_DIGEST_FAILURE, (SSL_ERROR_BASE + 127),
ER3(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 128),
"Incorrect signature algorithm specified in a digitally-signed element.")
ER3(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK, (SSL_ERROR_BASE + 129),
"The next protocol negotiation extension was enabled, but the callback was cleared prior to being needed.")
ER3(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL, (SSL_ERROR_BASE + 130),
"The server supports no protocols that the client advertises in the ALPN extension.")

View File

@ -51,16 +51,21 @@ static const ssl3CipherSuite nonDTLSSuites[] = {
*
* TLS DTLS
* 1.1 (0302) 1.0 (feff)
* 1.2 (0303) 1.2 (fefd)
*/
SSL3ProtocolVersion
dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
{
/* Anything other than TLS 1.1 is an error, so return
* the invalid version ffff. */
if (tlsv != SSL_LIBRARY_VERSION_TLS_1_1)
return 0xffff;
if (tlsv == SSL_LIBRARY_VERSION_TLS_1_1) {
return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
}
if (tlsv == SSL_LIBRARY_VERSION_TLS_1_2) {
return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
}
return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
/* Anything other than TLS 1.1 or 1.2 is an error, so return
* the invalid version 0xffff. */
return 0xffff;
}
/* Map known DTLS versions to known TLS versions.
@ -71,14 +76,18 @@ SSL3ProtocolVersion
dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
{
if (MSB(dtlsv) == 0xff) {
return 0;
return 0;
}
if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE)
return SSL_LIBRARY_VERSION_TLS_1_1;
if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
return SSL_LIBRARY_VERSION_TLS_1_1;
}
if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
return SSL_LIBRARY_VERSION_TLS_1_2;
}
/* Return a fictional higher version than we know of */
return SSL_LIBRARY_VERSION_TLS_1_1 + 1;
return SSL_LIBRARY_VERSION_TLS_1_2 + 1;
}
/* On this socket, Disable non-DTLS cipher suites in the argument's list */
@ -88,9 +97,9 @@ ssl3_DisableNonDTLSSuites(sslSocket * ss)
const ssl3CipherSuite * suite;
for (suite = nonDTLSSuites; *suite; ++suite) {
SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
PORT_Assert(rv == SECSuccess); /* else is coding error */
PORT_Assert(rv == SECSuccess); /* else is coding error */
}
return SECSuccess;
}
@ -101,17 +110,17 @@ ssl3_DisableNonDTLSSuites(sslSocket * ss)
*/
static DTLSQueuedMessage *
dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
const unsigned char *data, PRUint32 len)
const unsigned char *data, PRUint32 len)
{
DTLSQueuedMessage *msg = NULL;
msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
if (!msg)
return NULL;
return NULL;
msg->data = PORT_Alloc(len);
if (!msg->data) {
PORT_Free(msg);
PORT_Free(msg);
return NULL;
}
PORT_Memcpy(msg->data, data, len);
@ -132,7 +141,7 @@ static void
dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
{
if (!msg)
return;
return;
PORT_ZFree(msg->data, msg->len);
PORT_Free(msg);
@ -151,9 +160,9 @@ dtls_FreeHandshakeMessages(PRCList *list)
PRCList *cur_p;
while (!PR_CLIST_IS_EMPTY(list)) {
cur_p = PR_LIST_TAIL(list);
PR_REMOVE_LINK(cur_p);
dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
cur_p = PR_LIST_TAIL(list);
PR_REMOVE_LINK(cur_p);
dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
}
}
@ -204,18 +213,18 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
}
/* Parse the header */
type = buf.buf[0];
type = buf.buf[0];
message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
message_seq = (buf.buf[4] << 8) | buf.buf[5];
fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
if (message_length > MAX_HANDSHAKE_MSG_LEN) {
(void)ssl3_DecodeError(ss);
PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
return SECFailure;
}
#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
if (message_length > MAX_HANDSHAKE_MSG_LEN) {
(void)ssl3_DecodeError(ss);
PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
return SECFailure;
}
#undef MAX_HANDSHAKE_MSG_LEN
buf.buf += 12;
@ -229,7 +238,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
}
/* Sanity check the packet contents */
if ((fragment_length + fragment_offset) > message_length) {
if ((fragment_length + fragment_offset) > message_length) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
rv = SECFailure;
break;
@ -245,8 +254,8 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
* This is the common case for short messages
*/
if ((message_seq == ss->ssl3.hs.recvMessageSeq)
&& (fragment_offset == 0)
&& (fragment_length == message_length)) {
&& (fragment_offset == 0)
&& (fragment_length == message_length)) {
/* Complete next message. Process immediately */
ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
ss->ssl3.hs.msg_len = message_length;
@ -254,14 +263,14 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
/* At this point we are advancing our state machine, so
* we can free our last flight of messages */
dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
ss->ssl3.hs.recvdHighWater = -1;
dtls_CancelTimer(ss);
ss->ssl3.hs.recvdHighWater = -1;
dtls_CancelTimer(ss);
/* Reset the timer to the initial value if the retry counter
* is 0, per Sec. 4.2.4.1 */
if (ss->ssl3.hs.rtRetries == 0) {
ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
}
/* Reset the timer to the initial value if the retry counter
* is 0, per Sec. 4.2.4.1 */
if (ss->ssl3.hs.rtRetries == 0) {
ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
}
rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
if (rv == SECFailure) {
@ -269,68 +278,68 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
break;
}
} else {
if (message_seq < ss->ssl3.hs.recvMessageSeq) {
/* Case 3: we do an immediate retransmit if we're
* in a waiting state*/
if (ss->ssl3.hs.rtTimerCb == NULL) {
/* Ignore */
} else if (ss->ssl3.hs.rtTimerCb ==
dtls_RetransmitTimerExpiredCb) {
SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
SSL_GETPID(), ss->fd));
/* Check to see if we retransmitted recently. If so,
* suppress the triggered retransmit. This avoids
* retransmit wars after packet loss.
* This is not in RFC 5346 but should be
*/
if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
(ss->ssl3.hs.rtTimeoutMs / 4)) {
SSL_TRC(30,
("%d: SSL3[%d]: Shortcutting retransmit timer",
if (message_seq < ss->ssl3.hs.recvMessageSeq) {
/* Case 3: we do an immediate retransmit if we're
* in a waiting state*/
if (ss->ssl3.hs.rtTimerCb == NULL) {
/* Ignore */
} else if (ss->ssl3.hs.rtTimerCb ==
dtls_RetransmitTimerExpiredCb) {
SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
SSL_GETPID(), ss->fd));
/* Check to see if we retransmitted recently. If so,
* suppress the triggered retransmit. This avoids
* retransmit wars after packet loss.
* This is not in RFC 5346 but should be
*/
if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
(ss->ssl3.hs.rtTimeoutMs / 4)) {
SSL_TRC(30,
("%d: SSL3[%d]: Shortcutting retransmit timer",
SSL_GETPID(), ss->fd));
/* Cancel the timer and call the CB,
* which re-arms the timer */
dtls_CancelTimer(ss);
dtls_RetransmitTimerExpiredCb(ss);
rv = SECSuccess;
break;
} else {
SSL_TRC(30,
("%d: SSL3[%d]: We just retransmitted. Ignoring.",
/* Cancel the timer and call the CB,
* which re-arms the timer */
dtls_CancelTimer(ss);
dtls_RetransmitTimerExpiredCb(ss);
rv = SECSuccess;
break;
} else {
SSL_TRC(30,
("%d: SSL3[%d]: We just retransmitted. Ignoring.",
SSL_GETPID(), ss->fd));
rv = SECSuccess;
break;
}
} else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
/* Retransmit the messages and re-arm the timer
* Note that we are not backing off the timer here.
* The spec isn't clear and my reasoning is that this
* may be a re-ordered packet rather than slowness,
* so let's be aggressive. */
dtls_CancelTimer(ss);
rv = dtls_TransmitMessageFlight(ss);
if (rv == SECSuccess) {
rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
}
if (rv != SECSuccess)
return rv;
break;
}
} else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
/* Case 2
rv = SECSuccess;
break;
}
} else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
/* Retransmit the messages and re-arm the timer
* Note that we are not backing off the timer here.
* The spec isn't clear and my reasoning is that this
* may be a re-ordered packet rather than slowness,
* so let's be aggressive. */
dtls_CancelTimer(ss);
rv = dtls_TransmitMessageFlight(ss);
if (rv == SECSuccess) {
rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
}
if (rv != SECSuccess)
return rv;
break;
}
} else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
/* Case 2
*
* Ignore this message. This means we don't handle out of
* order complete messages that well, but we're still
* compliant and this probably does not happen often
* Ignore this message. This means we don't handle out of
* order complete messages that well, but we're still
* compliant and this probably does not happen often
*
* XXX OK for now. Maybe do something smarter at some point?
*/
} else {
/* Case 1
* XXX OK for now. Maybe do something smarter at some point?
*/
} else {
/* Case 1
*
* Buffer the fragment for reassembly
*/
* Buffer the fragment for reassembly
*/
/* Make room for the message */
if (ss->ssl3.hs.recvdHighWater == -1) {
PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
@ -347,8 +356,8 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
/* Reset the reassembly map */
ss->ssl3.hs.recvdHighWater = 0;
PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
ss->ssl3.hs.recvdFragments.space);
ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
ss->ssl3.hs.recvdFragments.space);
ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
ss->ssl3.hs.msg_len = message_length;
}
@ -381,7 +390,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
* case of adjacent fragments received in sequence
*/
if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
/* Either this is the adjacent fragment or an overlapping
/* Either this is the adjacent fragment or an overlapping
* fragment */
ss->ssl3.hs.recvdHighWater = fragment_offset +
fragment_length;
@ -397,9 +406,9 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
/* Now figure out the new high water mark if appropriate */
for (offset = ss->ssl3.hs.recvdHighWater;
offset < ss->ssl3.hs.msg_len; offset++) {
/* Note that this loop is not efficient, since it counts
* bit by bit. If we have a lot of out-of-order packets,
* we should optimize this */
/* Note that this loop is not efficient, since it counts
* bit by bit. If we have a lot of out-of-order packets,
* we should optimize this */
if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
OFFSET_MASK(offset)) {
ss->ssl3.hs.recvdHighWater++;
@ -418,25 +427,25 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
if (rv == SECFailure)
break; /* Skip rest of record */
/* At this point we are advancing our state machine, so
* we can free our last flight of messages */
dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
dtls_CancelTimer(ss);
/* At this point we are advancing our state machine, so
* we can free our last flight of messages */
dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
dtls_CancelTimer(ss);
/* If there have been no retries this time, reset the
* timer value to the default per Section 4.2.4.1 */
if (ss->ssl3.hs.rtRetries == 0) {
ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
}
/* If there have been no retries this time, reset the
* timer value to the default per Section 4.2.4.1 */
if (ss->ssl3.hs.rtRetries == 0) {
ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
}
}
}
}
buf.buf += fragment_length;
buf.buf += fragment_length;
buf.len -= fragment_length;
}
origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
/* XXX OK for now. In future handle rv == SECWouldBlock safely in order
* to deal with asynchronous certificate verification */
@ -461,10 +470,10 @@ SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
if (!msg) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
rv = SECFailure;
PORT_SetError(SEC_ERROR_NO_MEMORY);
rv = SECFailure;
} else {
PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
}
return rv;
@ -490,7 +499,7 @@ dtls_StageHandshakeMessage(sslSocket *ss)
/* This function is sometimes called when no data is actually to
* be staged, so just return SECSuccess. */
if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
return rv;
return rv;
rv = dtls_QueueMessage(ss, content_handshake,
ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
@ -522,11 +531,11 @@ dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
rv = dtls_TransmitMessageFlight(ss);
if (rv != SECSuccess)
return rv;
if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
ss->ssl3.hs.rtRetries = 0;
rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
}
if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
ss->ssl3.hs.rtRetries = 0;
rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
}
}
return rv;
@ -546,22 +555,22 @@ dtls_RetransmitTimerExpiredCb(sslSocket *ss)
ss->ssl3.hs.rtRetries++;
if (!(ss->ssl3.hs.rtRetries % 3)) {
/* If one of the messages was potentially greater than > MTU,
* then downgrade. Do this every time we have retransmitted a
* message twice, per RFC 6347 Sec. 4.1.1 */
dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
/* If one of the messages was potentially greater than > MTU,
* then downgrade. Do this every time we have retransmitted a
* message twice, per RFC 6347 Sec. 4.1.1 */
dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
}
rv = dtls_TransmitMessageFlight(ss);
if (rv == SECSuccess) {
/* Re-arm the timer */
rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
/* Re-arm the timer */
rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
}
if (rv == SECFailure) {
/* XXX OK for now. In future maybe signal the stack that we couldn't
* transmit. For now, let the read handle any real network errors */
/* XXX OK for now. In future maybe signal the stack that we couldn't
* transmit. For now, let the read handle any real network errors */
}
}
@ -591,87 +600,87 @@ dtls_TransmitMessageFlight(sslSocket *ss)
*/
PORT_Assert(!ss->pendingBuf.len);
for (msg_p = PR_LIST_HEAD(&ss->ssl3.hs.lastMessageFlight);
msg_p != &ss->ssl3.hs.lastMessageFlight;
msg_p = PR_NEXT_LINK(msg_p)) {
msg_p != &ss->ssl3.hs.lastMessageFlight;
msg_p = PR_NEXT_LINK(msg_p)) {
DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
/* The logic here is:
*
* 1. If this is a message that will not fit into the remaining
* space, then flush.
* 2. If the message will now fit into the remaining space,
* 1. If this is a message that will not fit into the remaining
* space, then flush.
* 2. If the message will now fit into the remaining space,
* encrypt, buffer, and loop.
* 3. If the message will not fit, then fragment.
*
* At the end of the function, flush.
* At the end of the function, flush.
*/
if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
/* The message will not fit into the remaining space, so flush */
rv = dtls_SendSavedWriteData(ss);
if (rv != SECSuccess)
break;
/* The message will not fit into the remaining space, so flush */
rv = dtls_SendSavedWriteData(ss);
if (rv != SECSuccess)
break;
room_left = ss->ssl3.mtu;
}
}
if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
/* The message will fit, so encrypt and then continue with the
* next packet */
* next packet */
sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
msg->data, msg->len,
ssl_SEND_FLAG_FORCE_INTO_BUFFER |
ssl_SEND_FLAG_USE_EPOCH);
msg->data, msg->len,
ssl_SEND_FLAG_FORCE_INTO_BUFFER |
ssl_SEND_FLAG_USE_EPOCH);
if (sent != msg->len) {
rv = SECFailure;
if (sent != -1) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
rv = SECFailure;
if (sent != -1) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
break;
}
}
room_left = ss->ssl3.mtu - ss->pendingBuf.len;
} else {
/* The message will not fit, so fragment.
*
* XXX OK for now. Arrange to coalesce the last fragment
* of this message with the next message if possible.
* That would be more efficient.
*/
* XXX OK for now. Arrange to coalesce the last fragment
* of this message with the next message if possible.
* That would be more efficient.
*/
PRUint32 fragment_offset = 0;
unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
* plausible MTU */
/* Assert that we have already flushed */
PORT_Assert(room_left == ss->ssl3.mtu);
/* Assert that we have already flushed */
PORT_Assert(room_left == ss->ssl3.mtu);
/* Case 3: We now need to fragment this message
* DTLS only supports fragmenting handshaking messages */
PORT_Assert(msg->type == content_handshake);
/* The headers consume 12 bytes so the smalles possible
* message (i.e., an empty one) is 12 bytes
*/
PORT_Assert(msg->len >= 12);
/* The headers consume 12 bytes so the smalles possible
* message (i.e., an empty one) is 12 bytes
*/
PORT_Assert(msg->len >= 12);
while ((fragment_offset + 12) < msg->len) {
PRUint32 fragment_len;
const unsigned char *content = msg->data + 12;
PRUint32 content_len = msg->len - 12;
/* The reason we use 8 here is that that's the length of
* the new DTLS data that we add to the header */
/* The reason we use 8 here is that that's the length of
* the new DTLS data that we add to the header */
fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
content_len - fragment_offset);
PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
/* Make totally sure that we are within the buffer.
* Note that the only way that fragment len could get
* adjusted here is if
PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
/* Make totally sure that we are within the buffer.
* Note that the only way that fragment len could get
* adjusted here is if
*
* (a) we are in release mode so the PORT_Assert is compiled out
* (b) either the MTU table is inconsistent with DTLS_MAX_MTU
* or ss->ssl3.mtu has become corrupt.
*/
fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
* (a) we are in release mode so the PORT_Assert is compiled out
* (b) either the MTU table is inconsistent with DTLS_MAX_MTU
* or ss->ssl3.mtu has become corrupt.
*/
fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
/* Construct an appropriate-sized fragment */
/* Type, length, sequence */
@ -691,25 +700,25 @@ dtls_TransmitMessageFlight(sslSocket *ss)
fragment_len);
/*
* Send the record. We do this in two stages
* 1. Encrypt
*/
* Send the record. We do this in two stages
* 1. Encrypt
*/
sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
fragment, fragment_len + 12,
ssl_SEND_FLAG_FORCE_INTO_BUFFER |
ssl_SEND_FLAG_USE_EPOCH);
ssl_SEND_FLAG_USE_EPOCH);
if (sent != (fragment_len + 12)) {
rv = SECFailure;
if (sent != -1) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
break;
}
/* 2. Flush */
rv = dtls_SendSavedWriteData(ss);
if (rv != SECSuccess)
break;
rv = SECFailure;
if (sent != -1) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
break;
}
/* 2. Flush */
rv = dtls_SendSavedWriteData(ss);
if (rv != SECSuccess)
break;
fragment_offset += fragment_len;
}
@ -718,7 +727,7 @@ dtls_TransmitMessageFlight(sslSocket *ss)
/* Finally, we need to flush */
if (rv == SECSuccess)
rv = dtls_SendSavedWriteData(ss);
rv = dtls_SendSavedWriteData(ss);
/* Give up the locks */
ssl_ReleaseSpecReadLock(ss);
@ -740,19 +749,19 @@ SECStatus dtls_SendSavedWriteData(sslSocket *ss)
sent = ssl_SendSavedWriteData(ss);
if (sent < 0)
return SECFailure;
return SECFailure;
/* We should always have complete writes b/c datagram sockets
* don't really block */
if (ss->pendingBuf.len > 0) {
ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
return SECFailure;
ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
return SECFailure;
}
/* Update the largest message sent so we can adjust the MTU
* estimate if necessary */
if (sent > ss->ssl3.hs.maxMessageSent)
ss->ssl3.hs.maxMessageSent = sent;
ss->ssl3.hs.maxMessageSent = sent;
return SECSuccess;
}
@ -767,16 +776,16 @@ SECStatus dtls_SendSavedWriteData(sslSocket *ss)
SECStatus
dtls_CompressMACEncryptRecord(sslSocket * ss,
DTLSEpoch epoch,
PRBool use_epoch,
PRBool use_epoch,
SSL3ContentType type,
const SSL3Opaque * pIn,
PRUint32 contentLen,
sslBuffer * wrBuf)
const SSL3Opaque * pIn,
PRUint32 contentLen,
sslBuffer * wrBuf)
{
SECStatus rv = SECFailure;
ssl3CipherSpec * cwSpec;
ssl_GetSpecReadLock(ss); /********************************/
ssl_GetSpecReadLock(ss); /********************************/
/* The reason for this switch-hitting code is that we might have
* a flight of records spanning an epoch boundary, e.g.,
@ -789,23 +798,23 @@ dtls_CompressMACEncryptRecord(sslSocket * ss,
* about which epoch to use is carried with the record.
*/
if (use_epoch) {
if (ss->ssl3.cwSpec->epoch == epoch)
cwSpec = ss->ssl3.cwSpec;
else if (ss->ssl3.pwSpec->epoch == epoch)
cwSpec = ss->ssl3.pwSpec;
else
cwSpec = NULL;
if (ss->ssl3.cwSpec->epoch == epoch)
cwSpec = ss->ssl3.cwSpec;
else if (ss->ssl3.pwSpec->epoch == epoch)
cwSpec = ss->ssl3.pwSpec;
else
cwSpec = NULL;
} else {
cwSpec = ss->ssl3.cwSpec;
cwSpec = ss->ssl3.cwSpec;
}
if (cwSpec) {
rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
PR_FALSE, type, pIn, contentLen,
wrBuf);
PR_FALSE, type, pIn, contentLen,
wrBuf);
} else {
PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
ssl_ReleaseSpecReadLock(ss); /************************************/
@ -838,9 +847,9 @@ SECStatus
dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
{
if (backoff) {
ss->ssl3.hs.rtTimeoutMs *= 2;
if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
ss->ssl3.hs.rtTimeoutMs *= 2;
if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
}
return dtls_StartTimer(ss, cb);
@ -868,18 +877,18 @@ void
dtls_CheckTimer(sslSocket *ss)
{
if (!ss->ssl3.hs.rtTimerCb)
return;
return;
if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
/* Timer has expired */
DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
/* Cancel the timer so that we can call the CB safely */
dtls_CancelTimer(ss);
PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
/* Timer has expired */
DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
/* Now call the CB */
cb(ss);
/* Cancel the timer so that we can call the CB safely */
dtls_CancelTimer(ss);
/* Now call the CB */
cb(ss);
}
}
@ -928,17 +937,17 @@ dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
int i;
if (advertised == 0) {
ss->ssl3.mtu = COMMON_MTU_VALUES[0];
SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
return;
ss->ssl3.mtu = COMMON_MTU_VALUES[0];
SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
return;
}
for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
if (COMMON_MTU_VALUES[i] <= advertised) {
ss->ssl3.mtu = COMMON_MTU_VALUES[i];
SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
return;
}
if (COMMON_MTU_VALUES[i] <= advertised) {
ss->ssl3.mtu = COMMON_MTU_VALUES[i];
SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
return;
}
}
/* Fallback */
@ -953,57 +962,57 @@ dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
SECStatus
dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
SECStatus rv;
PRInt32 temp;
SECItem cookie = {siBuffer, NULL, 0};
SSL3AlertDescription desc = illegal_parameter;
SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
SSL_GETPID(), ss->fd));
SSL_GETPID(), ss->fd));
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.ws != wait_server_hello) {
errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
desc = unexpected_message;
goto alert_loser;
desc = unexpected_message;
goto alert_loser;
}
/* The version */
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
if (temp < 0) {
goto loser; /* alert has been sent */
goto loser; /* alert has been sent */
}
if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
/* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */
goto alert_loser;
if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
temp != SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
goto alert_loser;
}
/* The cookie */
rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
if (rv != SECSuccess) {
goto loser; /* alert has been sent */
goto loser; /* alert has been sent */
}
if (cookie.len > DTLS_COOKIE_BYTES) {
desc = decode_error;
goto alert_loser; /* malformed. */
desc = decode_error;
goto alert_loser; /* malformed. */
}
PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
ss->ssl3.hs.cookieLen = cookie.len;
ssl_GetXmitBufLock(ss); /*******************************/
ssl_GetXmitBufLock(ss); /*******************************/
/* Now re-send the client hello */
rv = ssl3_SendClientHello(ss, PR_TRUE);
ssl_ReleaseXmitBufLock(ss); /*******************************/
ssl_ReleaseXmitBufLock(ss); /*******************************/
if (rv == SECSuccess)
return rv;
return rv;
alert_loser:
(void)SSL3_SendAlert(ss, alert_fatal, desc);
@ -1042,14 +1051,14 @@ dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
/* Out of range to the left */
if (seq < records->left) {
return -1;
return -1;
}
/* Out of range to the right; since we advance the window on
* receipt, that means that this packet has not been received
* yet */
if (seq > records->right)
return 0;
return 0;
offset = seq % DTLS_RECVD_RECORDS_WINDOW;
@ -1066,34 +1075,34 @@ dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
PRUint64 offset;
if (seq < records->left)
return;
return;
if (seq > records->right) {
PRUint64 new_left;
PRUint64 new_right;
PRUint64 right;
PRUint64 new_left;
PRUint64 new_right;
PRUint64 right;
/* Slide to the right; this is the tricky part
/* Slide to the right; this is the tricky part
*
* 1. new_top is set to have room for seq, on the
* next byte boundary by setting the right 8
* bits of seq
* 1. new_top is set to have room for seq, on the
* next byte boundary by setting the right 8
* bits of seq
* 2. new_left is set to compensate.
* 3. Zero all bits between top and new_top. Since
* this is a ring, this zeroes everything as-yet
* unseen. Because we always operate on byte
* boundaries, we can zero one byte at a time
*/
new_right = seq | 0x07;
new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
* unseen. Because we always operate on byte
* boundaries, we can zero one byte at a time
*/
new_right = seq | 0x07;
new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
for (right = records->right + 8; right <= new_right; right += 8) {
offset = right % DTLS_RECVD_RECORDS_WINDOW;
records->data[offset / 8] = 0;
}
for (right = records->right + 8; right <= new_right; right += 8) {
offset = right % DTLS_RECVD_RECORDS_WINDOW;
records->data[offset / 8] = 0;
}
records->right = new_right;
records->left = new_left;
records->right = new_right;
records->left = new_left;
}
offset = seq % DTLS_RECVD_RECORDS_WINDOW;

View File

@ -633,6 +633,7 @@ ssl3_CipherSuiteAllowedForVersionRange(
* TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA: never implemented
*/
return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0;
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
case TLS_RSA_WITH_AES_256_CBC_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
@ -645,6 +646,31 @@ ssl3_CipherSuiteAllowedForVersionRange(
case TLS_RSA_WITH_AES_128_GCM_SHA256:
case TLS_RSA_WITH_NULL_SHA256:
return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
/* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
* point formats.*/
case TLS_ECDH_ECDSA_WITH_NULL_SHA:
case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDH_RSA_WITH_NULL_SHA:
case TLS_ECDH_RSA_WITH_RC4_128_SHA:
case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_RSA_WITH_NULL_SHA:
case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0;
default:
return PR_TRUE;
}
@ -3471,6 +3497,14 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
SSL_GETPID(), ss->fd));
if (ws != wait_change_cipher) {
if (IS_DTLS(ss)) {
/* Ignore this because it's out of order. */
SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
"DTLS change_cipher_spec",
SSL_GETPID(), ss->fd));
buf->len = 0;
return SECSuccess;
}
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
return SECFailure;

View File

@ -56,10 +56,14 @@ static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
PRUint16 ex_type, SECItem *data);
static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static PRInt32 ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
@ -237,6 +241,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
{ ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
{ ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
{ ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
{ ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn },
{ ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
{ ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
{ ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
@ -559,7 +564,8 @@ ssl3_SendSessionTicketXtn(
/* handle an incoming Next Protocol Negotiation extension. */
static SECStatus
ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type,
SECItem *data)
{
if (ss->firstHsDone || data->len != 0) {
/* Clients MUST send an empty NPN extension, if any. */
@ -604,14 +610,93 @@ ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length)
return SECSuccess;
}
/* protocol selection handler for ALPN (server side) and NPN (client side) */
static SECStatus
ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
unsigned char resultBuffer[255];
SECItem result = { siBuffer, resultBuffer, 0 };
rv = ssl3_ValidateNextProtoNego(data->data, data->len);
if (rv != SECSuccess)
return rv;
PORT_Assert(ss->nextProtoCallback);
rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
result.data, &result.len, sizeof resultBuffer);
if (rv != SECSuccess)
return rv;
/* If the callback wrote more than allowed to |result| it has corrupted our
* stack. */
if (result.len > sizeof resultBuffer) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
if (ex_type == ssl_app_layer_protocol_xtn &&
ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) {
/* The callback might say OK, but then it's picked a default.
* That's OK for NPN, but not ALPN. */
SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
(void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
return SECFailure;
}
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
}
/* handle an incoming ALPN extension at the server */
static SECStatus
ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
int count;
SECStatus rv;
/* We expressly don't want to allow ALPN on renegotiation,
* despite it being permitted by the spec. */
if (ss->firstHsDone || data->len == 0) {
/* Clients MUST send a non-empty ALPN extension. */
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
return SECFailure;
}
/* unlike NPN, ALPN has extra redundant length information so that
* the extension is the same in both ClientHello and ServerHello */
count = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
if (count < 0) {
return SECFailure; /* fatal alert was sent */
}
if (count != data->len) {
return ssl3_DecodeError(ss);
}
if (!ss->nextProtoCallback) {
/* we're not configured for it */
return SECSuccess;
}
rv = ssl3_SelectAppProtocol(ss, ex_type, data);
if (rv != SECSuccess) {
return rv;
}
/* prepare to send back a response, if we negotiated */
if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) {
return ssl3_RegisterServerHelloExtensionSender(
ss, ex_type, ssl3_ServerSendAppProtoXtn);
}
return SECSuccess;
}
static SECStatus
ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
{
PORT_Assert(!ss->firstHsDone);
if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
@ -625,37 +710,16 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
return SECFailure;
}
rv = ssl3_ValidateNextProtoNego(data->data, data->len);
if (rv != SECSuccess)
return rv;
/* ss->nextProtoCallback cannot normally be NULL if we negotiated the
* extension. However, It is possible that an application erroneously
* cleared the callback between the time we sent the ClientHello and now.
*/
PORT_Assert(ss->nextProtoCallback != NULL);
/* We should only get this call if we sent the extension, so
* ss->nextProtoCallback needs to be non-NULL. However, it is possible
* that an application erroneously cleared the callback between the time
* we sent the ClientHello and now. */
if (!ss->nextProtoCallback) {
/* XXX Use a better error code. This is an application error, not an
* NSS bug. */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
return SECFailure;
}
rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
result.data, &result.len, sizeof resultBuffer);
if (rv != SECSuccess)
return rv;
/* If the callback wrote more than allowed to |result| it has corrupted our
* stack. */
if (result.len > sizeof resultBuffer) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
return ssl3_SelectAppProtocol(ss, ex_type, data);
}
static SECStatus
@ -796,6 +860,48 @@ loser:
return -1;
}
static PRInt32
ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
{
PRInt32 extension_length;
/* we're in over our heads if any of these fail */
PORT_Assert(ss->opt.enableALPN);
PORT_Assert(ss->ssl3.nextProto.data);
PORT_Assert(ss->ssl3.nextProto.len > 0);
PORT_Assert(ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED);
PORT_Assert(!ss->firstHsDone);
extension_length = 2 /* extension type */ + 2 /* extension length */ +
2 /* protocol name list */ + 1 /* name length */ +
ss->ssl3.nextProto.len;
if (append && maxBytes >= extension_length) {
SECStatus rv;
rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
if (rv != SECSuccess) {
return -1;
}
rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
if (rv != SECSuccess) {
return -1;
}
rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.nextProto.len + 1, 2);
if (rv != SECSuccess) {
return -1;
}
rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
ss->ssl3.nextProto.len, 1);
if (rv != SECSuccess) {
return -1;
}
} else if (maxBytes < extension_length) {
return 0;
}
return extension_length;
}
static SECStatus
ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)

View File

@ -106,7 +106,8 @@ typedef enum {
certificate_unobtainable = 111,
unrecognized_name = 112,
bad_certificate_status_response = 113,
bad_certificate_hash_value = 114
bad_certificate_hash_value = 114,
no_application_protocol = 120
} SSL3AlertDescription;

View File

@ -193,6 +193,9 @@ SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM = (SSL_ERROR_BASE + 126),
SSL_ERROR_DIGEST_FAILURE = (SSL_ERROR_BASE + 127),
SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK = (SSL_ERROR_BASE + 129),
SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL = (SSL_ERROR_BASE + 130),
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
#endif /* NO_SECURITY_ERROR_ENUM */

View File

@ -1,5 +1,5 @@
/*
* Various and sundry protocol constants. DON'T CHANGE THESE. These values
* Various and sundry protocol constants. DON'T CHANGE THESE. These values
* are mostly defined by the SSL2, SSL3, or TLS protocol specifications.
* Cipher kinds and ciphersuites are part of the public API.
*
@ -11,75 +11,77 @@
#define __sslproto_h_
/* All versions less than 3_0 are treated as SSL version 2 */
#define SSL_LIBRARY_VERSION_2 0x0002
#define SSL_LIBRARY_VERSION_3_0 0x0300
#define SSL_LIBRARY_VERSION_TLS_1_0 0x0301
#define SSL_LIBRARY_VERSION_TLS_1_1 0x0302
#define SSL_LIBRARY_VERSION_TLS_1_2 0x0303
#define SSL_LIBRARY_VERSION_2 0x0002
#define SSL_LIBRARY_VERSION_3_0 0x0300
#define SSL_LIBRARY_VERSION_TLS_1_0 0x0301
#define SSL_LIBRARY_VERSION_TLS_1_1 0x0302
#define SSL_LIBRARY_VERSION_TLS_1_2 0x0303
/* Note: this is the internal format, not the wire format */
#define SSL_LIBRARY_VERSION_DTLS_1_0 0x0302
#define SSL_LIBRARY_VERSION_DTLS_1_0 0x0302
#define SSL_LIBRARY_VERSION_DTLS_1_2 0x0303
/* deprecated old name */
#define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0
#define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0
/* The DTLS version used in the spec */
/* The DTLS versions used in the spec */
#define SSL_LIBRARY_VERSION_DTLS_1_0_WIRE ((~0x0100) & 0xffff)
#define SSL_LIBRARY_VERSION_DTLS_1_2_WIRE ((~0x0102) & 0xffff)
/* Header lengths of some of the messages */
#define SSL_HL_ERROR_HBYTES 3
#define SSL_HL_CLIENT_HELLO_HBYTES 9
#define SSL_HL_CLIENT_MASTER_KEY_HBYTES 10
#define SSL_HL_CLIENT_FINISHED_HBYTES 1
#define SSL_HL_SERVER_HELLO_HBYTES 11
#define SSL_HL_SERVER_VERIFY_HBYTES 1
#define SSL_HL_SERVER_FINISHED_HBYTES 1
#define SSL_HL_REQUEST_CERTIFICATE_HBYTES 2
#define SSL_HL_CLIENT_CERTIFICATE_HBYTES 6
#define SSL_HL_ERROR_HBYTES 3
#define SSL_HL_CLIENT_HELLO_HBYTES 9
#define SSL_HL_CLIENT_MASTER_KEY_HBYTES 10
#define SSL_HL_CLIENT_FINISHED_HBYTES 1
#define SSL_HL_SERVER_HELLO_HBYTES 11
#define SSL_HL_SERVER_VERIFY_HBYTES 1
#define SSL_HL_SERVER_FINISHED_HBYTES 1
#define SSL_HL_REQUEST_CERTIFICATE_HBYTES 2
#define SSL_HL_CLIENT_CERTIFICATE_HBYTES 6
/* Security handshake protocol codes */
#define SSL_MT_ERROR 0
#define SSL_MT_CLIENT_HELLO 1
#define SSL_MT_CLIENT_MASTER_KEY 2
#define SSL_MT_CLIENT_FINISHED 3
#define SSL_MT_SERVER_HELLO 4
#define SSL_MT_SERVER_VERIFY 5
#define SSL_MT_SERVER_FINISHED 6
#define SSL_MT_REQUEST_CERTIFICATE 7
#define SSL_MT_CLIENT_CERTIFICATE 8
#define SSL_MT_ERROR 0
#define SSL_MT_CLIENT_HELLO 1
#define SSL_MT_CLIENT_MASTER_KEY 2
#define SSL_MT_CLIENT_FINISHED 3
#define SSL_MT_SERVER_HELLO 4
#define SSL_MT_SERVER_VERIFY 5
#define SSL_MT_SERVER_FINISHED 6
#define SSL_MT_REQUEST_CERTIFICATE 7
#define SSL_MT_CLIENT_CERTIFICATE 8
/* Certificate types */
#define SSL_CT_X509_CERTIFICATE 0x01
#define SSL_CT_X509_CERTIFICATE 0x01
#if 0 /* XXX Not implemented yet */
#define SSL_PKCS6_CERTIFICATE 0x02
#define SSL_PKCS6_CERTIFICATE 0x02
#endif
#define SSL_AT_MD5_WITH_RSA_ENCRYPTION 0x01
#define SSL_AT_MD5_WITH_RSA_ENCRYPTION 0x01
/* Error codes */
#define SSL_PE_NO_CYPHERS 0x0001
#define SSL_PE_NO_CERTIFICATE 0x0002
#define SSL_PE_BAD_CERTIFICATE 0x0004
#define SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006
#define SSL_PE_NO_CYPHERS 0x0001
#define SSL_PE_NO_CERTIFICATE 0x0002
#define SSL_PE_BAD_CERTIFICATE 0x0004
#define SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006
/* Cypher kinds (not the spec version!) */
#define SSL_CK_RC4_128_WITH_MD5 0x01
#define SSL_CK_RC4_128_EXPORT40_WITH_MD5 0x02
#define SSL_CK_RC2_128_CBC_WITH_MD5 0x03
#define SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x04
#define SSL_CK_IDEA_128_CBC_WITH_MD5 0x05
#define SSL_CK_DES_64_CBC_WITH_MD5 0x06
#define SSL_CK_DES_192_EDE3_CBC_WITH_MD5 0x07
#define SSL_CK_RC4_128_WITH_MD5 0x01
#define SSL_CK_RC4_128_EXPORT40_WITH_MD5 0x02
#define SSL_CK_RC2_128_CBC_WITH_MD5 0x03
#define SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x04
#define SSL_CK_IDEA_128_CBC_WITH_MD5 0x05
#define SSL_CK_DES_64_CBC_WITH_MD5 0x06
#define SSL_CK_DES_192_EDE3_CBC_WITH_MD5 0x07
/* Cipher enables. These are used only for SSL_EnableCipher
* These values define the SSL2 suites, and do not colide with the
/* Cipher enables. These are used only for SSL_EnableCipher
* These values define the SSL2 suites, and do not colide with the
* SSL3 Cipher suites defined below.
*/
#define SSL_EN_RC4_128_WITH_MD5 0xFF01
#define SSL_EN_RC4_128_EXPORT40_WITH_MD5 0xFF02
#define SSL_EN_RC2_128_CBC_WITH_MD5 0xFF03
#define SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5 0xFF04
#define SSL_EN_IDEA_128_CBC_WITH_MD5 0xFF05
#define SSL_EN_DES_64_CBC_WITH_MD5 0xFF06
#define SSL_EN_DES_192_EDE3_CBC_WITH_MD5 0xFF07
#define SSL_EN_RC4_128_WITH_MD5 0xFF01
#define SSL_EN_RC4_128_EXPORT40_WITH_MD5 0xFF02
#define SSL_EN_RC2_128_CBC_WITH_MD5 0xFF03
#define SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5 0xFF04
#define SSL_EN_IDEA_128_CBC_WITH_MD5 0xFF05
#define SSL_EN_DES_64_CBC_WITH_MD5 0xFF06
#define SSL_EN_DES_192_EDE3_CBC_WITH_MD5 0xFF07
/* Deprecated SSL 3.0 & libssl names replaced by IANA-registered TLS names. */
#ifndef SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES
@ -117,66 +119,66 @@
#define TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
#endif
#define TLS_NULL_WITH_NULL_NULL 0x0000
#define TLS_NULL_WITH_NULL_NULL 0x0000
#define TLS_RSA_WITH_NULL_MD5 0x0001
#define TLS_RSA_WITH_NULL_SHA 0x0002
#define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003
#define TLS_RSA_WITH_RC4_128_MD5 0x0004
#define TLS_RSA_WITH_RC4_128_SHA 0x0005
#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006
#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007
#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008
#define TLS_RSA_WITH_DES_CBC_SHA 0x0009
#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000a
#define TLS_RSA_WITH_NULL_MD5 0x0001
#define TLS_RSA_WITH_NULL_SHA 0x0002
#define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003
#define TLS_RSA_WITH_RC4_128_MD5 0x0004
#define TLS_RSA_WITH_RC4_128_SHA 0x0005
#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006
#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007
#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008
#define TLS_RSA_WITH_DES_CBC_SHA 0x0009
#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000a
#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000b
#define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000c
#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000d
#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000e
#define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000f
#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000b
#define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000c
#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000d
#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000e
#define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000f
#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011
#define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012
#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014
#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015
#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011
#define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012
#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014
#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015
#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017
#define TLS_DH_anon_WITH_RC4_128_MD5 0x0018
#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019
#define TLS_DH_anon_WITH_DES_CBC_SHA 0x001a
#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001b
#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017
#define TLS_DH_anon_WITH_RC4_128_MD5 0x0018
#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019
#define TLS_DH_anon_WITH_DES_CBC_SHA 0x001a
#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001b
#define SSL_FORTEZZA_DMS_WITH_NULL_SHA 0x001c /* deprecated */
#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA 0x001d /* deprecated */
#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA 0x001e /* deprecated */
#define SSL_FORTEZZA_DMS_WITH_NULL_SHA 0x001c /* deprecated */
#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA 0x001d /* deprecated */
#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA 0x001e /* deprecated */
#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
#define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
#define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
#define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
#define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
#define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
#define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
#define TLS_RSA_WITH_NULL_SHA256 0x003B
#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
#define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
#define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
#define TLS_RSA_WITH_NULL_SHA256 0x003B
#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0041
#define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0042
#define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0043
#define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0044
#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0045
#define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA 0x0046
#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0041
#define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0042
#define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0043
#define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0044
#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0045
#define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA 0x0046
#define TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x0062
#define TLS_RSA_EXPORT1024_WITH_RC4_56_SHA 0x0064
@ -187,14 +189,14 @@
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0084
#define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0085
#define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0086
#define TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0087
#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0088
#define TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA 0x0089
#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0084
#define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0085
#define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0086
#define TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0087
#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0088
#define TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA 0x0089
#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096
#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096
#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
@ -204,7 +206,7 @@
* Must NEVER be chosen by server. SSL 3.0 server acknowledges by sending
* back an empty Renegotiation Info (RI) server hello extension.
*/
#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
/* Cipher Suite Values starting with 0xC000 are defined in informational
* RFCs.
@ -248,18 +250,18 @@
#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
/* Netscape "experimental" cipher suites. */
#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1
#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1
/* New non-experimental openly spec'ed versions of those cipher suites. */
#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA 0xfeff
#define SSL_RSA_FIPS_WITH_DES_CBC_SHA 0xfefe
#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA 0xfeff
#define SSL_RSA_FIPS_WITH_DES_CBC_SHA 0xfefe
/* DTLS-SRTP cipher suites from RFC 5764 */
/* If you modify this, also modify MAX_DTLS_SRTP_CIPHER_SUITES in sslimpl.h */
#define SRTP_AES128_CM_HMAC_SHA1_80 0x0001
#define SRTP_AES128_CM_HMAC_SHA1_32 0x0002
#define SRTP_NULL_HMAC_SHA1_80 0x0005
#define SRTP_NULL_HMAC_SHA1_32 0x0006
#define SRTP_AES128_CM_HMAC_SHA1_80 0x0001
#define SRTP_AES128_CM_HMAC_SHA1_32 0x0002
#define SRTP_NULL_HMAC_SHA1_80 0x0005
#define SRTP_NULL_HMAC_SHA1_32 0x0006
#endif /* __sslproto_h_ */

View File

@ -1370,6 +1370,11 @@ DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd)
return ssl_ImportFD(model, fd, ssl_variant_datagram);
}
/* SSL_SetNextProtoCallback is used to select an application protocol
* for ALPN and NPN. For ALPN, this runs on the server; for NPN it
* runs on the client. */
/* Note: The ALPN version doesn't allow for the use of a default, setting a
* status of SSL_NEXT_PROTO_NO_OVERLAP is treated as a failure. */
SECStatus
SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback,
void *arg)
@ -1390,7 +1395,7 @@ SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback,
return SECSuccess;
}
/* ssl_NextProtoNegoCallback is set as an NPN callback for the case when
/* ssl_NextProtoNegoCallback is set as an ALPN/NPN callback when
* SSL_SetNextProtoNego is used.
*/
static SECStatus
@ -1409,12 +1414,6 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd,
return SECFailure;
}
if (protos_len == 0) {
/* The server supports the extension, but doesn't have any protocols
* configured. In this case we request our favoured protocol. */
goto pick_first;
}
/* For each protocol in server preference, see if we support it. */
for (i = 0; i < protos_len; ) {
for (j = 0; j < ss->opt.nextProtoNego.len; ) {
@ -1431,7 +1430,10 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd,
i += 1 + (unsigned int)protos[i];
}
pick_first:
/* The other side supports the extension, and either doesn't have any
* protocols configured, or none of its options match ours. In this case we
* request our favoured protocol. */
/* This will be treated as a failure for ALPN. */
ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
result = ss->opt.nextProtoNego.data;

View File

@ -1176,6 +1176,201 @@ cert_extensions()
done < ${QADIR}/cert/certext.txt
}
cert_make_with_param()
{
DIRPASS="$1"
CERTNAME="$2"
MAKE="$3"
SUBJ="$4"
EXTRA="$5"
EXPECT="$6"
TESTNAME="$7"
echo certutil ${DIRPASS} -s "${SUBJ}" ${MAKE} ${CERTNAME} ${EXTRA}
${BINDIR}/certutil ${DIRPASS} -s "${SUBJ}" ${MAKE} ${CERTNAME} ${EXTRA}
RET=$?
if [ "${RET}" -ne "${EXPECT}" ]; then
# if we expected failure to create, then delete unexpected certificate
if [ "${EXPECT}" -ne 0 ]; then
${BINDIR}/certutil ${DIRPASS} -D ${CERTNAME}
fi
CERTFAILED=1
html_failed "${TESTNAME} (${COUNT}) - ${EXTRA}"
cert_log "ERROR: ${TESTNAME} - ${EXTRA} failed"
return 1
fi
html_passed "${TESTNAME} (${COUNT})"
return 0
}
cert_list_and_count_dns()
{
DIRPASS="$1"
CERTNAME="$2"
EXPECT="$3"
EXPECTCOUNT="$4"
TESTNAME="$5"
echo certutil ${DIRPASS} -L ${CERTNAME}
${BINDIR}/certutil ${DIRPASS} -L ${CERTNAME}
RET=$?
if [ "${RET}" -ne "${EXPECT}" ]; then
CERTFAILED=1
html_failed "${TESTNAME} (${COUNT}) - list and count"
cert_log "ERROR: ${TESTNAME} - list and count failed"
return 1
fi
LISTCOUNT=`${BINDIR}/certutil ${DIRPASS} -L ${CERTNAME} | grep -wc DNS`
if [ "${LISTCOUNT}" -ne "${EXPECTCOUNT}" ]; then
CERTFAILED=1
html_failed "${TESTNAME} (${COUNT}) - list and count"
cert_log "ERROR: ${TESTNAME} - list and count failed"
return 1
fi
html_passed "${TESTNAME} (${COUNT})"
return 0
}
cert_dump_ext_to_file()
{
DIRPASS="$1"
CERTNAME="$2"
OID="$3"
OUTFILE="$4"
EXPECT="$5"
TESTNAME="$6"
echo certutil ${DIRPASS} -L ${CERTNAME} --dump-ext-val ${OID}
echo "writing output to ${OUTFILE}"
${BINDIR}/certutil ${DIRPASS} -L ${CERTNAME} --dump-ext-val ${OID} > ${OUTFILE}
RET=$?
if [ "${RET}" -ne "${EXPECT}" ]; then
CERTFAILED=1
html_failed "${TESTNAME} (${COUNT}) - dump to file"
cert_log "ERROR: ${TESTNAME} - dump to file failed"
return 1
fi
html_passed "${TESTNAME} (${COUNT})"
return 0
}
cert_delete()
{
DIRPASS="$1"
CERTNAME="$2"
EXPECT="$3"
TESTNAME="$4"
echo certutil ${DIRPASS} -D ${CERTNAME}
${BINDIR}/certutil ${DIRPASS} -D ${CERTNAME}
RET=$?
if [ "${RET}" -ne "${EXPECT}" ]; then
CERTFAILED=1
html_failed "${TESTNAME} (${COUNT}) - delete cert"
cert_log "ERROR: ${TESTNAME} - delete cert failed"
return 1
fi
html_passed "${TESTNAME} (${COUNT})"
return 0
}
cert_inc_count()
{
COUNT=`expr ${COUNT} + 1`
}
############################## cert_crl_ssl ############################
# test adding subject-alt-name, dumping, and adding generic extension
########################################################################
cert_san_and_generic_extensions()
{
EXTDUMP=${CERT_EXTENSIONS_DIR}/sanext.der
DIR="-d ${CERT_EXTENSIONS_DIR} -f ${R_PWFILE}"
CERTNAME="-n WithSAN"
MAKE="-S -t ,, -x -z ${R_NOISE_FILE}"
SUBJ="CN=example.com"
TESTNAME="san-and-generic-extensions"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extSAN example.com" 255 \
"create cert with invalid SAN parameter"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extSAN example.com,dns:www.example.com" 255 \
"create cert with invalid SAN parameter"
TN="create cert with valid SAN parameter"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extSAN dns:example.com,dns:www.example.com" 0 \
"${TN}"
cert_inc_count
cert_list_and_count_dns "${DIR}" "${CERTNAME}" 0 2 \
"${TN}"
cert_inc_count
cert_dump_ext_to_file "${DIR}" "${CERTNAME}" "2.5.29.17" "${EXTDUMP}" 0 \
"dump extension 2.5.29.17 to file ${EXTDUMP}"
cert_inc_count
cert_delete "${DIR}" "${CERTNAME}" 0 \
"${TN}"
cert_inc_count
cert_list_and_count_dns "${DIR}" "${CERTNAME}" 255 0 \
"expect failure to list cert, because we deleted it"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extGeneric ${EXTDUMP}" 255 \
"create cert with invalid generic ext parameter"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extGeneric not-critical:${EXTDUMP}" 255 \
"create cert with invalid generic ext parameter"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extGeneric not-critical:${EXTDUMP},2.5.29.17:critical:${EXTDUMP}" 255 \
"create cert with invalid generic ext parameter"
TN="create cert with valid generic ext parameter"
cert_inc_count
cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
"--extGeneric 2.5.29.17:not-critical:${EXTDUMP}" 0 \
"${TN}"
cert_inc_count
cert_list_and_count_dns "${DIR}" "${CERTNAME}" 0 2 \
"${TN}"
cert_inc_count
cert_delete "${DIR}" "${CERTNAME}" 0 \
"${TN}"
cert_inc_count
cert_list_and_count_dns "${DIR}" "${CERTNAME}" 255 0 \
"expect failure to list cert, because we deleted it"
}
############################## cert_crl_ssl ############################
# local shell function to generate certs and crls for SSL tests
########################################################################
@ -1513,6 +1708,7 @@ if [ -z "$NSS_TEST_DISABLE_FIPS" ]; then
fi
cert_eccurves
cert_extensions
cert_san_and_generic_extensions
cert_test_password
cert_test_distrust
cert_test_ocspresp