/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*/
#include "pkcs1sig.h"
#include "hasht.h"
#include "secerr.h"
#include "secasn1t.h"
#include "secoid.h"
typedef struct pkcs1PrefixStr pkcs1Prefix;
struct pkcs1PrefixStr {
unsigned int len;
PRUint8 *data;
};
/* The value for SGN_PKCS1_DIGESTINFO_MAX_PREFIX_LEN_EXCLUDING_OID is based on
* the possible prefix encodings as explained below .
*/
#define MAX_PREFIX_LEN_EXCLUDING_OID 10
static SECStatus
encodePrefix(const SECOidData *hashOid, unsigned int digestLen,
pkcs1Prefix *prefix, PRBool withParams)
{
/* with params coding is:
* Sequence ( 2 bytes ) {
* Sequence ( 2 bytes ) {
* Oid ( 2 bytes ) {
* Oid value ( derOid - > oid . len )
* }
* NULL ( 2 bytes )
* }
* OCTECT ( 2 bytes ) ;
*
* without params coding is :
* Sequence ( 2 bytes ) {
* Sequence ( 2 bytes ) {
* Oid ( 2 bytes ) {
* Oid value ( derOid - > oid . len )
* }
* }
* OCTECT ( 2 bytes ) ;
*/
unsigned int innerSeqLen = 2 + hashOid->oid.len;
unsigned int outerSeqLen = 2 + innerSeqLen + 2 + digestLen;
unsigned int extra = 0 ;
if (withParams) {
innerSeqLen += 2 ;
outerSeqLen += 2 ;
extra = 2 ;
}
if (innerSeqLen >= 128 ||
outerSeqLen >= 128 ||
(outerSeqLen + 2 - digestLen) >
(MAX_PREFIX_LEN_EXCLUDING_OID + hashOid->oid.len)) {
/* this is actually a library failure, It shouldn't happen */
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
prefix->len = 6 + hashOid->oid.len + extra + 2 ;
prefix->data = PORT_Alloc(prefix->len);
if (!prefix->data) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
prefix->data[0 ] = SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED;
prefix->data[1 ] = outerSeqLen;
prefix->data[2 ] = SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED;
prefix->data[3 ] = innerSeqLen;
prefix->data[4 ] = SEC_ASN1_OBJECT_ID;
prefix->data[5 ] = hashOid->oid.len;
PORT_Memcpy(&prefix->data[6 ], hashOid->oid.data, hashOid->oid.len);
if (withParams) {
prefix->data[6 + hashOid->oid.len] = SEC_ASN1_NULL;
prefix->data[6 + hashOid->oid.len + 1 ] = 0 ;
}
prefix->data[6 + hashOid->oid.len + extra] = SEC_ASN1_OCTET_STRING;
prefix->data[6 + hashOid->oid.len + extra + 1 ] = digestLen;
return SECSuccess;
}
SECStatus
_SGN_VerifyPKCS1DigestInfo(SECOidTag digestAlg,
const SECItem *digest,
const SECItem *dataRecoveredFromSignature,
PRBool unsafeAllowMissingParameters)
{
SECOidData *hashOid;
pkcs1Prefix prefix;
SECStatus rv;
if (!digest || !digest->data ||
!dataRecoveredFromSignature || !dataRecoveredFromSignature->data) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
hashOid = SECOID_FindOIDByTag(digestAlg);
if (hashOid == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
prefix.data = NULL;
rv = encodePrefix(hashOid, digest->len, &prefix, PR_TRUE);
if (rv == SECSuccess) {
/* We don't attempt to avoid timing attacks on these comparisons because
* signature verification is a public key operation , not a private key
* operation .
*/
if (dataRecoveredFromSignature->len != prefix.len + digest->len) {
PRBool lengthMismatch = PR_TRUE;
#ifdef NSS_PKCS1_AllowMissingParameters
if (unsafeAllowMissingParameters) {
if (prefix.data) {
PORT_Free(prefix.data);
prefix.data = NULL;
}
rv = encodePrefix(hashOid, digest->len, &prefix, PR_FALSE);
if (rv != SECSuccess ||
dataRecoveredFromSignature->len == prefix.len + digest->len) {
lengthMismatch = PR_FALSE;
}
}
#endif
if (lengthMismatch) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
rv = SECFailure;
}
}
}
if (rv == SECSuccess) {
if (memcmp(dataRecoveredFromSignature->data, prefix.data, prefix.len) ||
memcmp(dataRecoveredFromSignature->data + prefix.len, digest->data,
digest->len)) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
rv = SECFailure;
}
}
if (prefix.data) {
PORT_Free(prefix.data);
}
return rv;
}
Messung V0.5 in Prozent C=97 H=100 G=98
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-30)
¤
*© Formatika GbR, Deutschland