1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/util/pkcs1sig.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,169 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + */ 1.8 + 1.9 +#include "pkcs1sig.h" 1.10 +#include "hasht.h" 1.11 +#include "secerr.h" 1.12 +#include "secasn1t.h" 1.13 +#include "secoid.h" 1.14 + 1.15 +typedef struct pkcs1PrefixStr pkcs1Prefix; 1.16 +struct pkcs1PrefixStr { 1.17 + unsigned int len; 1.18 + PRUint8 *data; 1.19 +}; 1.20 + 1.21 +typedef struct pkcs1PrefixesStr pkcs1Prefixes; 1.22 +struct pkcs1PrefixesStr { 1.23 + unsigned int digestLen; 1.24 + pkcs1Prefix prefixWithParams; 1.25 + pkcs1Prefix prefixWithoutParams; 1.26 +}; 1.27 + 1.28 +/* The value for SGN_PKCS1_DIGESTINFO_MAX_PREFIX_LEN_EXCLUDING_OID is based on 1.29 + * the possible prefix encodings as explained below. 1.30 + */ 1.31 +#define MAX_PREFIX_LEN_EXCLUDING_OID 10 1.32 + 1.33 +static SECStatus 1.34 +encodePrefix(const SECOidData *hashOid, unsigned int digestLen, 1.35 + pkcs1Prefix *prefix, PRBool withParams) 1.36 +{ 1.37 + /* with params coding is: 1.38 + * Sequence (2 bytes) { 1.39 + * Sequence (2 bytes) { 1.40 + * Oid (2 bytes) { 1.41 + * Oid value (derOid->oid.len) 1.42 + * } 1.43 + * NULL (2 bytes) 1.44 + * } 1.45 + * OCTECT (2 bytes); 1.46 + * 1.47 + * without params coding is: 1.48 + * Sequence (2 bytes) { 1.49 + * Sequence (2 bytes) { 1.50 + * Oid (2 bytes) { 1.51 + * Oid value (derOid->oid.len) 1.52 + * } 1.53 + * } 1.54 + * OCTECT (2 bytes); 1.55 + */ 1.56 + 1.57 + unsigned int innerSeqLen = 2 + hashOid->oid.len; 1.58 + unsigned int outerSeqLen = 2 + innerSeqLen + 2 + digestLen; 1.59 + unsigned int extra = 0; 1.60 + 1.61 + if (withParams) { 1.62 + innerSeqLen += 2; 1.63 + outerSeqLen += 2; 1.64 + extra = 2; 1.65 + } 1.66 + 1.67 + if (innerSeqLen >= 128 || 1.68 + outerSeqLen >= 128 || 1.69 + (outerSeqLen + 2 - digestLen) > 1.70 + (MAX_PREFIX_LEN_EXCLUDING_OID + hashOid->oid.len)) { 1.71 + /* this is actually a library failure, It shouldn't happen */ 1.72 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.73 + return SECFailure; 1.74 + } 1.75 + 1.76 + prefix->len = 6 + hashOid->oid.len + extra + 2; 1.77 + prefix->data = PORT_Alloc(prefix->len); 1.78 + if (!prefix->data) { 1.79 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.80 + return SECFailure; 1.81 + } 1.82 + 1.83 + prefix->data[0] = SEC_ASN1_SEQUENCE|SEC_ASN1_CONSTRUCTED; 1.84 + prefix->data[1] = outerSeqLen; 1.85 + prefix->data[2] = SEC_ASN1_SEQUENCE|SEC_ASN1_CONSTRUCTED; 1.86 + prefix->data[3] = innerSeqLen; 1.87 + prefix->data[4] = SEC_ASN1_OBJECT_ID; 1.88 + prefix->data[5] = hashOid->oid.len; 1.89 + PORT_Memcpy(&prefix->data[6], hashOid->oid.data, hashOid->oid.len); 1.90 + if (withParams) { 1.91 + prefix->data[6 + hashOid->oid.len] = SEC_ASN1_NULL; 1.92 + prefix->data[6 + hashOid->oid.len + 1] = 0; 1.93 + } 1.94 + prefix->data[6 + hashOid->oid.len + extra] = SEC_ASN1_OCTET_STRING; 1.95 + prefix->data[6 + hashOid->oid.len + extra + 1] = digestLen; 1.96 + 1.97 + return SECSuccess; 1.98 +} 1.99 + 1.100 +SECStatus 1.101 +_SGN_VerifyPKCS1DigestInfo(SECOidTag digestAlg, 1.102 + const SECItem* digest, 1.103 + const SECItem* dataRecoveredFromSignature, 1.104 + PRBool unsafeAllowMissingParameters) 1.105 +{ 1.106 + SECOidData *hashOid; 1.107 + pkcs1Prefixes pp; 1.108 + const pkcs1Prefix* expectedPrefix; 1.109 + SECStatus rv, rv2, rv3; 1.110 + 1.111 + if (!digest || !digest->data || 1.112 + !dataRecoveredFromSignature || !dataRecoveredFromSignature->data) { 1.113 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.114 + return SECFailure; 1.115 + } 1.116 + 1.117 + hashOid = SECOID_FindOIDByTag(digestAlg); 1.118 + if (hashOid == NULL) { 1.119 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.120 + return SECFailure; 1.121 + } 1.122 + 1.123 + pp.digestLen = digest->len; 1.124 + pp.prefixWithParams.data = NULL; 1.125 + pp.prefixWithoutParams.data = NULL; 1.126 + 1.127 + rv2 = encodePrefix(hashOid, pp.digestLen, &pp.prefixWithParams, PR_TRUE); 1.128 + rv3 = encodePrefix(hashOid, pp.digestLen, &pp.prefixWithoutParams, PR_FALSE); 1.129 + 1.130 + rv = SECSuccess; 1.131 + if (rv2 != SECSuccess || rv3 != SECSuccess) { 1.132 + rv = SECFailure; 1.133 + } 1.134 + 1.135 + if (rv == SECSuccess) { 1.136 + /* We don't attempt to avoid timing attacks on these comparisons because 1.137 + * signature verification is a public key operation, not a private key 1.138 + * operation. 1.139 + */ 1.140 + 1.141 + if (dataRecoveredFromSignature->len == 1.142 + pp.prefixWithParams.len + pp.digestLen) { 1.143 + expectedPrefix = &pp.prefixWithParams; 1.144 + } else if (unsafeAllowMissingParameters && 1.145 + dataRecoveredFromSignature->len == 1.146 + pp.prefixWithoutParams.len + pp.digestLen) { 1.147 + expectedPrefix = &pp.prefixWithoutParams; 1.148 + } else { 1.149 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.150 + rv = SECFailure; 1.151 + } 1.152 + } 1.153 + 1.154 + if (rv == SECSuccess) { 1.155 + if (memcmp(dataRecoveredFromSignature->data, expectedPrefix->data, 1.156 + expectedPrefix->len) || 1.157 + memcmp(dataRecoveredFromSignature->data + expectedPrefix->len, 1.158 + digest->data, digest->len)) { 1.159 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.160 + rv = SECFailure; 1.161 + } 1.162 + } 1.163 + 1.164 + if (pp.prefixWithParams.data) { 1.165 + PORT_Free(pp.prefixWithParams.data); 1.166 + } 1.167 + if (pp.prefixWithoutParams.data) { 1.168 + PORT_Free(pp.prefixWithoutParams.data); 1.169 + } 1.170 + 1.171 + return rv; 1.172 +}