示例#1
0
文件: TackNss.c 项目: tack/tackc
TACK_RETVAL tackNssVerifyFunc(uint8_t publicKeyBytes[TACK_PUBKEY_LENGTH],
                              uint8_t signature[TACK_SIG_LENGTH],
                              uint8_t *data,
                              uint32_t dataLength)
{
  SECItem signatureItem;
  SECItem hashItem;
  uint8_t hashBuffer[TACK_HASH_LENGTH];

  SECKEYPublicKey *publicKey = getPublicKeyFromBytes(publicKeyBytes);
  PK11_HashBuf(SEC_OID_SHA256, hashBuffer, data, dataLength);

  signatureItem.data = signature;
  signatureItem.len  = TACK_SIG_LENGTH;

  hashItem.data      = hashBuffer;
  hashItem.len       = sizeof(hashBuffer);

  uint32_t result = PK11_Verify(publicKey, &signatureItem, &hashItem, NULL);  

  SECKEY_DestroyPublicKey(publicKey);
  
  if (result == SECSuccess) return TACK_OK;
  else                      return TACK_ERR_BAD_SIGNATURE;
}
示例#2
0
/*
 *  c a l c u l a t e _ M D 5 _ r a n g e
 *
 *  Calculate the MD5 digest on a range of bytes in
 *  the specified fopen'd file. Returns base64.
 *
 */
static int	
calculate_MD5_range (FILE *fp, long r1, long r2, JAR_Digest *dig)
{
    int	num;
    int	range;
    unsigned char	*buf;
    SECStatus rv;

    range = r2 - r1;

    /* position to the beginning of range */
    fseek (fp, r1, SEEK_SET);

    buf = (unsigned char *) PORT_ZAlloc (range);
    if (buf == NULL)
	out_of_memory();

    if ((num = fread (buf, 1, range, fp)) != range) {
	PR_fprintf(errorFD, "%s: expected %d bytes, got %d\n", PROGRAM_NAME,
	     		range, num);
	errorCount++;
	exit (ERRX);
    }

    rv = PK11_HashBuf(SEC_OID_MD5, dig->md5, buf, range);
    if (rv == SECSuccess) {
	rv =PK11_HashBuf(SEC_OID_SHA1, dig->sha1, buf, range);
    }
    if (rv != SECSuccess) {
	PR_fprintf(errorFD, "%s: can't generate digest context\n",
	     PROGRAM_NAME);
	errorCount++;
	exit (ERRX);
    }

    PORT_Free (buf);

    return 0;
}
示例#3
0
int do_hash(char *src, int src_size, char *dst, int algo)
{
	SECStatus err;

	NSS_NoDB_Init(NULL);
	err = PK11_HashBuf(algo, (unsigned char *)dst, (unsigned char *)src,
			   src_size);
	if (err == SECFailure) {
		syslog(LOG_ERR, "%s: PK11_HashBuf() error; SECFailure = [%d]; "
		       "PORT_GetError() = [%d]\n", __FUNCTION__, SECFailure,
		       PORT_GetError());
		err = -EINVAL;
		goto out;
	}
out:
	return (int)err;
}
示例#4
0
SECStatus
DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
{
  static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
                "TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
  if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
    PR_NOT_REACHED("invalid hash length");
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }
  if (item.len >
      static_cast<decltype(item.len)>(std::numeric_limits<int32_t>::max())) {
    PR_NOT_REACHED("large OCSP responses should have already been rejected");
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }
  return PK11_HashBuf(SEC_OID_SHA1, digestBuf, item.data,
                      static_cast<int32_t>(item.len));
}
static nsresult
GetCertFingerprintByOidTag(CERTCertificate* nsscert,
                           SECOidTag aOidTag, 
                           nsCString &fp)
{
  unsigned int hash_len = HASH_ResultLenByOidTag(aOidTag);
  nsRefPtr<nsStringBuffer> fingerprint = nsStringBuffer::Alloc(hash_len);
  if (!fingerprint)
    return NS_ERROR_OUT_OF_MEMORY;

  PK11_HashBuf(aOidTag, (unsigned char*)fingerprint->Data(), 
               nsscert->derCert.data, nsscert->derCert.len);

  SECItem fpItem;
  fpItem.data = (unsigned char*)fingerprint->Data();
  fpItem.len = hash_len;

  fp.Adopt(CERT_Hexify(&fpItem, 1));
  return NS_OK;
}
示例#6
0
/* compute the thumbprint of the DER cert and create a digest info
 * to store it in and return the digest info.
 * a return of NULL indicates an error.
 */
SGNDigestInfo *
sec_pkcs12_compute_thumbprint(SECItem *der_cert)
{
    SGNDigestInfo *thumb = NULL;
    SECItem digest;
    PRArenaPool *temparena = NULL;
    SECStatus rv = SECFailure;

    if(der_cert == NULL)
	return NULL;

    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if(temparena == NULL) {
	return NULL;
    }

    digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
						    sizeof(unsigned char) * 
						    SHA1_LENGTH);
    /* digest data and create digest info */
    if(digest.data != NULL) {
	digest.len = SHA1_LENGTH;
	rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data, 
	                  der_cert->len);
	if(rv == SECSuccess) {
	    thumb = SGN_CreateDigestInfo(SEC_OID_SHA1, 
					 digest.data, 
					 digest.len);
	} else {
	    PORT_SetError(SEC_ERROR_NO_MEMORY);
	}
    } else {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
    }

    PORT_FreeArena(temparena, PR_TRUE);

    return thumb;
}
示例#7
0
int do_hash(char *src, int src_size, char *dst, int algo)
{
#ifdef ENABLE_NSS
	SECStatus err;
#else
	gcry_md_hd_t hd;
	gcry_error_t err = 0;
	unsigned char * hash;
	unsigned int mdlen;
#endif /* #ifdef ENABLE_NSS */

#ifdef ENABLE_NSS
	NSS_NoDB_Init(NULL);
	err = PK11_HashBuf(algo, (unsigned char *)dst, (unsigned char *)src,
			   src_size);
	if (err == SECFailure) {
		syslog(LOG_ERR, "%s: PK11_HashBuf() error; SECFailure = [%d]; "
		       "PORT_GetError() = [%d]\n", __FUNCTION__, SECFailure,
		       PORT_GetError());
		err = -EINVAL;
		goto out;
	}
#else
	err = gcry_md_open(&hd, algo, 0);
	mdlen = gcry_md_get_algo_dlen(algo);
	if (err) {
		syslog(LOG_ERR, "Failed to open hash algo [%d]: "
		       "[%d]\n", algo, err);
		goto out;
	}
	gcry_md_write(hd, src, src_size);
	hash = gcry_md_read(hd, algo);
	memcpy(dst, hash, mdlen);
	gcry_md_close(hd);
#endif /* #ifdef ENABLE_NSS */
out:
	return (int)err;
}
示例#8
0
Result
DigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
{
  static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
                "TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
  if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
    PR_NOT_REACHED("invalid hash length");
    return Result::FATAL_ERROR_INVALID_ARGS;
  }
  SECItem itemSECItem = UnsafeMapInputToSECItem(item);
  if (itemSECItem.len >
        static_cast<decltype(itemSECItem.len)>(
          std::numeric_limits<int32_t>::max())) {
    PR_NOT_REACHED("large items should not be possible here");
    return Result::FATAL_ERROR_INVALID_ARGS;
  }
  SECStatus srv = PK11_HashBuf(SEC_OID_SHA1, digestBuf, itemSECItem.data,
                               static_cast<int32_t>(itemSECItem.len));
  if (srv != SECSuccess) {
    return MapPRErrorCodeToResult(PR_GetError());
  }
  return Success;
}
示例#9
0
NS_IMETHODIMP
nsNSSCertificate::GetMd5Fingerprint(nsAString &_md5Fingerprint)
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  _md5Fingerprint.Truncate();
  unsigned char fingerprint[20];
  SECItem fpItem;
  memset(fingerprint, 0, sizeof fingerprint);
  PK11_HashBuf(SEC_OID_MD5, fingerprint, 
               mCert->derCert.data, mCert->derCert.len);
  fpItem.data = fingerprint;
  fpItem.len = MD5_LENGTH;
  char *fpStr = CERT_Hexify(&fpItem, 1);
  if (fpStr) {
    _md5Fingerprint = NS_ConvertASCIItoUTF16(fpStr);
    PORT_Free(fpStr);
    return NS_OK;
  }
  return NS_ERROR_FAILURE;
}
示例#10
0
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
// "The hash shall be calculated over the value (excluding tag and length) of
// the subject public key field in the issuer's certificate."
static der::Result
MatchIssuerKey(const SECItem& issuerKeyHash, const CERTCertificate& issuer,
               /*out*/ bool& match)
{
  if (issuerKeyHash.len != SHA1_LENGTH)  {
    return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  }

  // TODO(bug 966856): support SHA-2 hashes

  // Copy just the length and data pointer (nothing needs to be freed) of the
  // subject public key so we can convert the length from bits to bytes, which
  // is what the digest function expects.
  SECItem spk = issuer.subjectPublicKeyInfo.subjectPublicKey;
  DER_ConvertBitString(&spk);

  static uint8_t hashBuf[SHA1_LENGTH];
  if (PK11_HashBuf(SEC_OID_SHA1, hashBuf, spk.data, spk.len) != SECSuccess) {
    return der::Failure;
  }

  match = !memcmp(hashBuf, issuerKeyHash.data, issuerKeyHash.len);
  return der::Success;
}
示例#11
0
SECItem*
CreateEncodedOCSPRequest(PLArenaPool* arena,
                         const CERTCertificate* cert,
                         const CERTCertificate* issuerCert)
{
  if (!arena || !cert || !issuerCert) {
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return nullptr;
  }

  // We do not add any extensions to the request.

  // RFC 6960 says "An OCSP client MAY wish to specify the kinds of response
  // types it understands. To do so, it SHOULD use an extension with the OID
  // id-pkix-ocsp-response." This use of MAY and SHOULD is unclear. MSIE11
  // on Windows 8.1 does not include any extensions, whereas NSS has always
  // included the id-pkix-ocsp-response extension. Avoiding the sending the
  // extension is better for OCSP GET because it makes the request smaller,
  // and thus more likely to fit within the 255 byte limit for OCSP GET that
  // is specified in RFC 5019 Section 5.

  // Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.

  // Since we don't know whether the OCSP responder supports anything other
  // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
  // issuerKeyHash.
  static const uint8_t hashAlgorithm[11] = {
    0x30, 0x09,                               // SEQUENCE
    0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, //   OBJECT IDENTIFIER id-sha1
    0x05, 0x00,                               //   NULL
  };
  static const uint8_t hashLen = SHA1_LENGTH;

  static const unsigned int totalLenWithoutSerialNumberData
    = 2                             // OCSPRequest
    + 2                             //   tbsRequest
    + 2                             //     requestList
    + 2                             //       Request
    + 2                             //         reqCert (CertID)
    + PR_ARRAY_SIZE(hashAlgorithm)  //           hashAlgorithm
    + 2 + hashLen                   //           issuerNameHash
    + 2 + hashLen                   //           issuerKeyHash
    + 2;                            //           serialNumber (header)

  // The only way we could have a request this large is if the serialNumber was
  // ridiculously and unreasonably large. RFC 5280 says "Conforming CAs MUST
  // NOT use serialNumber values longer than 20 octets." With this restriction,
  // we allow for some amount of non-conformance with that requirement while
  // still ensuring we can encode the length values in the ASN.1 TLV structures
  // in a single byte.
  if (issuerCert->serialNumber.len > 127u - totalLenWithoutSerialNumberData) {
    PR_SetError(SEC_ERROR_BAD_DATA, 0);
    return nullptr;
  }

  uint8_t totalLen = static_cast<uint8_t>(totalLenWithoutSerialNumberData +
    cert->serialNumber.len);

  SECItem* encodedRequest = SECITEM_AllocItem(arena, nullptr, totalLen);
  if (!encodedRequest) {
    return nullptr;
  }

  uint8_t* d = encodedRequest->data;
  *d++ = 0x30; *d++ = totalLen - 2;  // OCSPRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 4;  //   tbsRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 6;  //     requestList (SEQUENCE OF)
  *d++ = 0x30; *d++ = totalLen - 8;  //       Request (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 10; //         reqCert (CertID SEQUENCE)

  // reqCert.hashAlgorithm
  for (size_t i = 0; i < PR_ARRAY_SIZE(hashAlgorithm); ++i) {
    *d++ = hashAlgorithm[i];
  }

  // reqCert.issuerNameHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  if (PK11_HashBuf(SEC_OID_SHA1, d, issuerCert->derSubject.data,
                   issuerCert->derSubject.len) != SECSuccess) {
    return nullptr;
  }
  d += hashLen;

  // reqCert.issuerKeyHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  SECItem key = issuerCert->subjectPublicKeyInfo.subjectPublicKey;
  DER_ConvertBitString(&key);
  if (PK11_HashBuf(SEC_OID_SHA1, d, key.data, key.len) != SECSuccess) {
    return nullptr;
  }
  d += hashLen;

  // reqCert.serialNumber (INTEGER)
  *d++ = 0x02; // INTEGER
  *d++ = static_cast<uint8_t>(cert->serialNumber.len);
  for (size_t i = 0; i < cert->serialNumber.len; ++i) {
    *d++ = cert->serialNumber.data[i];
  }

  PR_ASSERT(d == encodedRequest->data + totalLen);

  return encodedRequest;
}
示例#12
0
NSS_IMPLEMENT NSSTrust *
nssTrust_Create (
  nssPKIObject *object,
  NSSItem *certData
)
{
    PRStatus status;
    PRUint32 i;
    PRUint32 lastTrustOrder, myTrustOrder;
    unsigned char sha1_hashcmp[SHA1_LENGTH];
    unsigned char sha1_hashin[SHA1_LENGTH];
    NSSItem sha1_hash;
    NSSTrust *rvt;
    nssCryptokiObject *instance;
    nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection;
    SECStatus rv; /* Should be stan flavor */
    PRBool stepUp;

    lastTrustOrder = 1<<16; /* just make it big */
    PR_ASSERT(object->instances != NULL && object->numInstances > 0);
    rvt = nss_ZNEW(object->arena, NSSTrust);
    if (!rvt) {
	return (NSSTrust *)NULL;
    }
    rvt->object = *object;

    /* should be stan flavor of Hashbuf */
    rv = PK11_HashBuf(SEC_OID_SHA1,sha1_hashcmp,certData->data,certData->size);
    if (rv != SECSuccess) {
	return (NSSTrust *)NULL;
    }
    sha1_hash.data = sha1_hashin;
    sha1_hash.size = sizeof (sha1_hashin);
    /* trust has to peek into the base object members */
    nssPKIObject_Lock(object);
    for (i=0; i<object->numInstances; i++) {
	instance = object->instances[i];
	myTrustOrder = nssToken_GetTrustOrder(instance->token);
	status = nssCryptokiTrust_GetAttributes(instance, NULL,
						&sha1_hash,
	                                        &serverAuth,
	                                        &clientAuth,
	                                        &codeSigning,
	                                        &emailProtection,
	                                        &stepUp);
	if (status != PR_SUCCESS) {
	    nssPKIObject_Unlock(object);
	    return (NSSTrust *)NULL;
	}
	if (PORT_Memcmp(sha1_hashin,sha1_hashcmp,SHA1_LENGTH) != 0) {
	    nssPKIObject_Unlock(object);
	    return (NSSTrust *)NULL;
	}
	if (rvt->serverAuth == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->serverAuth = serverAuth;
	}
	if (rvt->clientAuth == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->clientAuth = clientAuth;
	}
	if (rvt->emailProtection == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->emailProtection = emailProtection;
	}
	if (rvt->codeSigning == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->codeSigning = codeSigning;
	}
	rvt->stepUpApproved = stepUp;
	lastTrustOrder = myTrustOrder;
    }
    nssPKIObject_Unlock(object);
    return rvt;
}
示例#13
0
// CertID          ::=     SEQUENCE {
//        hashAlgorithm       AlgorithmIdentifier,
//        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
//        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
//        serialNumber        CertificateSerialNumber }
static inline der::Result
CertID(der::Input& input, const Context& context, /*out*/ bool& match)
{
  match = false;

  SECAlgorithmID hashAlgorithm;
  if (der::Nested(input, der::SEQUENCE,
                  bind(der::AlgorithmIdentifier, _1, ref(hashAlgorithm)))
         != der::Success) {
    return der::Failure;
  }

  SECItem issuerNameHash;
  if (der::Skip(input, der::OCTET_STRING, issuerNameHash) != der::Success) {
    return der::Failure;
  }

  SECItem issuerKeyHash;
  if (der::Skip(input, der::OCTET_STRING, issuerKeyHash) != der::Success) {
    return der::Failure;
  }

  SECItem serialNumber;
  if (der::CertificateSerialNumber(input, serialNumber) != der::Success) {
    return der::Failure;
  }

  const CERTCertificate& cert = context.cert;
  const CERTCertificate& issuerCert = context.issuerCert;

  if (!SECITEM_ItemsAreEqual(&serialNumber, &cert.serialNumber)) {
    // This does not reference the certificate we're interested in.
    // Consume the rest of the input and return successfully to
    // potentially continue processing other responses.
    input.SkipToEnd();
    return der::Success;
  }

  // TODO: support SHA-2 hashes.

  SECOidTag hashAlg = SECOID_GetAlgorithmTag(&hashAlgorithm);
  if (hashAlg != SEC_OID_SHA1) {
    // Again, not interested in this response. Consume input, return success.
    input.SkipToEnd();
    return der::Success;
  }

  if (issuerNameHash.len != SHA1_LENGTH) {
    return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  }

  // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
  // "The hash shall be calculated over the DER encoding of the
  // issuer's name field in the certificate being checked."
  uint8_t hashBuf[SHA1_LENGTH];
  if (PK11_HashBuf(SEC_OID_SHA1, hashBuf, cert.derIssuer.data,
                   cert.derIssuer.len) != SECSuccess) {
    return der::Failure;
  }
  if (memcmp(hashBuf, issuerNameHash.data, issuerNameHash.len)) {
    // Again, not interested in this response. Consume input, return success.
    input.SkipToEnd();
    return der::Success;
  }

  return MatchIssuerKey(issuerKeyHash, issuerCert, match);
}
示例#14
0
static SECStatus
ConvertCertificate(SECItem *sdder, char *nickname, CERTCertTrust *trust,
                   PRBool excludeCert, PRBool excludeHash)
{
    SECStatus rv = SECSuccess;
    CERTCertificate *cert;
    unsigned char sha1_hash[SHA1_LENGTH];
    unsigned char md5_hash[MD5_LENGTH];
    SECItem *serial = NULL;
    PRBool step_up = PR_FALSE;
    const char *trust_info;

    cert = CERT_DecodeDERCertificate(sdder, PR_FALSE, nickname);
    if (!cert) {
	return SECFailure;
    }
    serial = SEC_ASN1EncodeItem(NULL,NULL,cert,serialTemplate);
    if (!serial) {
	return SECFailure;
    }
    
    if (!excludeCert) {
	printf("\n#\n# Certificate \"%s\"\n#\n",nickname);
	print_info(sdder, cert);
	printf("CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n");
	printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
	printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
	printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
	printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
	printf("CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n");
	printf("CKA_SUBJECT MULTILINE_OCTAL\n");
	dumpbytes(cert->derSubject.data,cert->derSubject.len);
	printf("END\n");
	printf("CKA_ID UTF8 \"0\"\n");
	printf("CKA_ISSUER MULTILINE_OCTAL\n");
	dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
	printf("END\n");
	printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
	dumpbytes(serial->data,serial->len);
	printf("END\n");
	printf("CKA_VALUE MULTILINE_OCTAL\n");
	dumpbytes(sdder->data,sdder->len);
	printf("END\n");
    }
    
    if ((trust->sslFlags | trust->emailFlags | trust->objectSigningFlags) 
         == CERTDB_TERMINAL_RECORD)
      trust_info = "Distrust";
    else
      trust_info = "Trust for";
    
    printf("\n# %s \"%s\"\n", trust_info, nickname);
    print_info(sdder, cert);

    printf("CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST\n");
    printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
    printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
    printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
    printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
    
    if (!excludeHash) {
	PK11_HashBuf(SEC_OID_SHA1, sha1_hash, sdder->data, sdder->len);
	printf("CKA_CERT_SHA1_HASH MULTILINE_OCTAL\n");
	dumpbytes(sha1_hash,SHA1_LENGTH);
	printf("END\n");
	PK11_HashBuf(SEC_OID_MD5, md5_hash, sdder->data, sdder->len);
	printf("CKA_CERT_MD5_HASH MULTILINE_OCTAL\n");
	dumpbytes(md5_hash,MD5_LENGTH);
	printf("END\n");
    }

    printf("CKA_ISSUER MULTILINE_OCTAL\n");
    dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
    printf("END\n");
    printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
    dumpbytes(serial->data,serial->len);
    printf("END\n");
    
    printf("CKA_TRUST_SERVER_AUTH CK_TRUST %s\n",
				getTrustString(trust->sslFlags));
    printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST %s\n",
				getTrustString(trust->emailFlags));
    printf("CKA_TRUST_CODE_SIGNING CK_TRUST %s\n",
				getTrustString(trust->objectSigningFlags));
#ifdef notdef
    printf("CKA_TRUST_CLIENT_AUTH CK_TRUST CKT_NSS_TRUSTED\n");
    printf("CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
    printf("CKA_TRUST_NON_REPUDIATION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
    printf("CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
    printf("CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
    printf("CKA_TRUST_KEY_AGREEMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
    printf("CKA_TRUST_KEY_CERT_SIGN CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
#endif
    
    step_up = (trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
    printf("CKA_TRUST_STEP_UP_APPROVED CK_BBOOL %s\n",
                step_up ? "CK_TRUE" : "CK_FALSE");

    PORT_Free(sdder->data);
    return(rv);

}
示例#15
0
PRBool
pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
{
  PRArenaPool *arena;

  CK_ATTRIBUTE tobjTemplate[] = {
    { CKA_CLASS, NULL, 0 },
    { CKA_CERT_SHA1_HASH, NULL, 0 },
  };

  CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
  CK_OBJECT_HANDLE tobjID;
  unsigned char sha1_hash[SHA1_LENGTH];

  CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth;

  PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);

  PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
  PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash, 
                SHA1_LENGTH);

  tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, 
                                     sizeof(tobjTemplate)/sizeof(tobjTemplate[0]));
  if( CK_INVALID_HANDLE == tobjID ) {
    return PR_FALSE;
  }

  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if( NULL == arena ) return PR_FALSE;

  /* Unfortunately, it seems that PK11_GetAttributes doesn't deal
   * well with nonexistent attributes.  I guess we have to check 
   * the trust info fields one at a time.
   */

  /* We could verify CKA_CERT_HASH here */

  /* We could verify CKA_EXPIRES here */


  /* "Purpose" trust information */
  serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
  clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH);
  codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
  emailProtection = pk11_GetTrustField(slot, arena, tobjID, 
						CKA_TRUST_EMAIL_PROTECTION);
  /* Here's where the fun logic happens.  We have to map back from the 
   * key usage, extended key usage, purpose, and possibly other trust values 
   * into the old trust-flags bits.  */

  /* First implementation: keep it simple for testing.  We can study what other
   * mappings would be appropriate and add them later.. fgmr 20000724 */

  if ( serverAuth ==  CKT_NSS_TRUSTED ) {
    trust->sslFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
  }

  if ( serverAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | 
							CERTDB_NS_TRUSTED_CA;
  }
  if ( clientAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->sslFlags |=  CERTDB_TRUSTED_CLIENT_CA ;
  }

  if ( emailProtection == CKT_NSS_TRUSTED ) {
    trust->emailFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
  }

  if ( emailProtection == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  }

  if( codeSigning == CKT_NSS_TRUSTED ) {
    trust->objectSigningFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
  }

  if( codeSigning == CKT_NSS_TRUSTED_DELEGATOR ) {
    trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  }

  /* There's certainly a lot more logic that can go here.. */

  PORT_FreeArena(arena, PR_FALSE);

  return PR_TRUE;
}
示例#16
0
static PRStatus
IdentityInfoInit()
{
  for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) {
    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];

    SECStatus rv;
    CERTIssuerAndSN ias;

    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64));
    PR_ASSERT(rv == SECSuccess);
    if (rv != SECSuccess) {
      return PR_FAILURE;
    }
    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber,
                                 const_cast<char*>(entry.serial_base64));
    PR_ASSERT(rv == SECSuccess);
    if (rv != SECSuccess) {
      SECITEM_FreeItem(&ias.derIssuer, false);
      return PR_FAILURE;
    }

    ias.serialNumber.type = siUnsignedInteger;

    entry.cert = CERT_FindCertByIssuerAndSN(nullptr, &ias);

    SECITEM_FreeItem(&ias.derIssuer, false);
    SECITEM_FreeItem(&ias.serialNumber, false);

    // If an entry is missing in the NSS root database, it may be because the
    // root database is out of sync with what we expect (e.g. a different
    // version of system NSS is installed). We will just silently avoid
    // treating that root cert as EV.
    if (!entry.cert) {
#ifdef DEBUG
      // The debug CA info is at position 0, and is NOT on the NSS root db
      if (iEV == 0) {
        continue;
      }
#endif
      PR_NOT_REACHED("Could not find EV root in NSS storage");
      continue;
    }

    unsigned char certFingerprint[20];
    rv = PK11_HashBuf(SEC_OID_SHA1, certFingerprint,
                      entry.cert->derCert.data, entry.cert->derCert.len);
    PR_ASSERT(rv == SECSuccess);
    if (rv == SECSuccess) {
      bool same = !memcmp(certFingerprint, entry.ev_root_sha1_fingerprint, 20);
      PR_ASSERT(same);
      if (same) {

        SECItem ev_oid_item;
        ev_oid_item.data = nullptr;
        ev_oid_item.len = 0;
        rv = SEC_StringToOID(nullptr, &ev_oid_item, entry.dotted_oid, 0);
        PR_ASSERT(rv == SECSuccess);
        if (rv == SECSuccess) {
          entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name);
          if (entry.oid_tag == SEC_OID_UNKNOWN) {
            rv = SECFailure;
          }
          SECITEM_FreeItem(&ev_oid_item, false);
        }
      } else {
        PR_SetError(SEC_ERROR_BAD_DATA, 0);
        rv = SECFailure;
      }
    }

    if (rv != SECSuccess) {
      CERT_DestroyCertificate(entry.cert);
      entry.cert = nullptr;
      entry.oid_tag = SEC_OID_UNKNOWN;
      return PR_FAILURE;
    }
  }

  return PR_SUCCESS;
}
示例#17
0
static int
cmmf_create_witness_and_challenge(PRArenaPool     *poolp,
                                  CMMFChallenge   *challenge,
                                  long             inRandom,
                                  SECItem         *senderDER,
                                  SECKEYPublicKey *inPubKey,
                                  void            *passwdArg)
{
    SECItem       *encodedRandNum;
    SECItem        encodedRandStr = {siBuffer, NULL, 0};
    SECItem       *dummy;
    unsigned char *randHash, *senderHash, *encChal=NULL;
    unsigned       modulusLen = 0;
    SECStatus      rv = SECFailure;
    CMMFRand       randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
    PK11SlotInfo  *slot;
    PK11SymKey    *symKey = NULL;
    CK_OBJECT_HANDLE id;
    CERTSubjectPublicKeyInfo *spki = NULL;


    encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
                                           inRandom);
    encodedRandNum = &challenge->randomNumber;
    randHash   = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    if (randHash == NULL) {
        goto loser;
    }
    rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data,
                      (PRUint32)encodedRandNum->len);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
                      (PRUint32)senderDER->len);
    if (rv != SECSuccess) {
        goto loser;
    }
    challenge->witness.data = randHash;
    challenge->witness.len  = SHA1_LENGTH;

    randStr.integer    = *encodedRandNum;
    randStr.senderHash.data = senderHash;
    randStr.senderHash.len  = SHA1_LENGTH;
    dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr,
                               CMMFRandTemplate);
    if (dummy != &encodedRandStr) {
        rv = SECFailure;
        goto loser;
    }
    /* XXXX Now I have to encrypt encodedRandStr and stash it away. */
    modulusLen = SECKEY_PublicKeyStrength(inPubKey);
    encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen);
    if (encChal == NULL) {
        rv = SECFailure;
        goto loser;
    }
    slot =PK11_GetBestSlotWithAttributes(CKM_RSA_PKCS, CKF_WRAP, 0, passwdArg);
    if (slot == NULL) {
        rv = SECFailure;
        goto loser;
    }
    id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE);
    /* In order to properly encrypt the data, we import as a symmetric
     * key, and then wrap that key.  That in essence encrypts the data.
     * This is the method recommended in the PK11 world in order
     * to prevent threading issues as well as breaking any other semantics
     * the PK11 libraries depend on.
     */
    symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
                               CKA_VALUE, &encodedRandStr, passwdArg);
    if (symKey == NULL) {
        rv = SECFailure;
        goto loser;
    }
    challenge->challenge.data = encChal;
    challenge->challenge.len  = modulusLen;
    rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey,
                            &challenge->challenge);
    PK11_FreeSlot(slot);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
    crmf_get_public_value(inPubKey, &challenge->key);
    /* Fall through */
loser:
    if (spki != NULL) {
        SECKEY_DestroySubjectPublicKeyInfo(spki);
    }
    if (encodedRandStr.data != NULL) {
        PORT_Free(encodedRandStr.data);
    }
    if (encodedRandNum != NULL) {
        SECITEM_FreeItem(encodedRandNum, PR_TRUE);
    }
    if (symKey != NULL) {
        PK11_FreeSymKey(symKey);
    }
    return rv;
}
示例#18
0
/* generate KEYS -- as per PKCS12 section 7.  
 * only used for MAC
 */
SECItem *
sec_pkcs12_generate_key_from_password(SECOidTag algorithm, 
				      SECItem *salt, 
				      SECItem *password) 
{
    unsigned char *pre_hash=NULL;
    unsigned char *hash_dest=NULL;
    SECStatus res;
    PRArenaPool *poolp;
    SECItem *key = NULL;
    int key_len = 0;

    if((salt == NULL) || (password == NULL)) {
	return NULL;
    }

    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if(poolp == NULL) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	return NULL;
    }

    pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * 
						 (salt->len+password->len));
    if(pre_hash == NULL) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	goto loser;
    }

    hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp, 
					sizeof(unsigned char) * SHA1_LENGTH);
    if(hash_dest == NULL) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	goto loser;
    }

    PORT_Memcpy(pre_hash, salt->data, salt->len);
    /* handle password of 0 length case */
    if(password->len > 0) {
	PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len);
    }

    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash, 
                       (salt->len+password->len));
    if(res == SECFailure) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	goto loser;
    }

    switch(algorithm) {
	case SEC_OID_SHA1:
	    if(key_len == 0)
		key_len = 16;
	    key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
	    if(key == NULL) {
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		goto loser;
	    }
	    key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) 
						     * key_len);
	    if(key->data == NULL) {
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		goto loser;
	    }
	    key->len = key_len;
	    PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH-key->len], key->len);
	    break;
	default:
	    goto loser;
	    break;
    }

    PORT_FreeArena(poolp, PR_TRUE);
    return key;

loser:
    PORT_FreeArena(poolp, PR_TRUE);
    if(key != NULL) {
	SECITEM_ZfreeItem(key, PR_TRUE);
    }
    return NULL;
}
示例#19
0
/* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
 * because it is not known how long the message actually is.  String
 * manipulation routines will not necessarily work because msg may have
 * imbedded NULLs
 */
static SECItem *
sec_pkcs12_generate_old_mac(SECItem *key, 
			    SECItem *msg)
{
    SECStatus res;
    PRArenaPool *temparena = NULL;
    unsigned char *hash_dest=NULL, *hash_src1=NULL, *hash_src2 = NULL;
    int i;
    SECItem *mac = NULL;

    if((key == NULL) || (msg == NULL))
        goto loser;

    /* allocate return item */
    mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    if(mac == NULL)
    	return NULL;
    mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char)
    	* SHA1_LENGTH);
    mac->len = SHA1_LENGTH;
    if(mac->data == NULL)
	goto loser;

    /* allocate temporary items */
    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if(temparena == NULL)
	goto loser;

    hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena,
    	sizeof(unsigned char) * (16+msg->len));
    if(hash_src1 == NULL)
        goto loser;

    hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena,
   	sizeof(unsigned char) * (SHA1_LENGTH+16));
    if(hash_src2 == NULL)
        goto loser;

    hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena, 
   	sizeof(unsigned char) * SHA1_LENGTH);
    if(hash_dest == NULL)
        goto loser;

    /* perform mac'ing as per PKCS 12 */

    /* first round of hashing */
    for(i = 0; i < 16; i++)
	hash_src1[i] = key->data[i] ^ 0x36;
    PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len);
    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16+msg->len));
    if(res == SECFailure)
	goto loser;

    /* second round of hashing */
    for(i = 0; i < 16; i++)
	hash_src2[i] = key->data[i] ^ 0x5c;
    PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH);
    res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH+16);
    if(res == SECFailure)
	goto loser;

    PORT_FreeArena(temparena, PR_TRUE);
    return mac;

loser:
    if(temparena != NULL)
	PORT_FreeArena(temparena, PR_TRUE);
    if(mac != NULL)
	SECITEM_ZfreeItem(mac, PR_TRUE);
    return NULL;
}
示例#20
0
NSS_IMPLEMENT NSSTrust *
nssTrust_Create (
  nssPKIObject *object,
  NSSItem *certData
)
{
    PRStatus status;
    PRUint32 i;
    PRUint32 lastTrustOrder, myTrustOrder;
    unsigned char sha1_hashcmp[SHA1_LENGTH];
    unsigned char sha1_hashin[SHA1_LENGTH];
    NSSItem sha1_hash;
    NSSTrust *rvt;
    nssCryptokiObject *instance;
    nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection;
    SECStatus rv; /* Should be stan flavor */
    PRBool stepUp;

    lastTrustOrder = 1<<16; /* just make it big */
    PR_ASSERT(object->instances != NULL && object->numInstances > 0);
    rvt = nss_ZNEW(object->arena, NSSTrust);
    if (!rvt) {
	return (NSSTrust *)NULL;
    }
    rvt->object = *object;

    /* should be stan flavor of Hashbuf */
    rv = PK11_HashBuf(SEC_OID_SHA1,sha1_hashcmp,certData->data,certData->size);
    if (rv != SECSuccess) {
	return (NSSTrust *)NULL;
    }
    sha1_hash.data = sha1_hashin;
    sha1_hash.size = sizeof (sha1_hashin);
    /* trust has to peek into the base object members */
    nssPKIObject_Lock(object);
    for (i=0; i<object->numInstances; i++) {
	instance = object->instances[i];
	myTrustOrder = nssToken_GetTrustOrder(instance->token);
	status = nssCryptokiTrust_GetAttributes(instance, NULL,
						&sha1_hash,
	                                        &serverAuth,
	                                        &clientAuth,
	                                        &codeSigning,
	                                        &emailProtection,
	                                        &stepUp);
	if (status != PR_SUCCESS) {
	    nssPKIObject_Unlock(object);
	    return (NSSTrust *)NULL;
	}
	/* if no hash is specified, then trust applies to all certs with
	 * this issuer/SN. NOTE: This is only true for entries that
	 * have distrust and unknown record */
	if (!(
            /* we continue if there is no hash, and the trust type is
	     * safe to accept without a hash ... or ... */
	     ((sha1_hash.size == 0)  && 
		nssTrust_IsSafeToIgnoreCertHash(serverAuth,clientAuth,
		codeSigning, emailProtection,stepUp)) 
	   ||
            /* we have a hash of the correct size, and it matches */
            ((sha1_hash.size == SHA1_LENGTH) && (PORT_Memcmp(sha1_hashin,
	        sha1_hashcmp,SHA1_LENGTH) == 0))   )) {
	    nssPKIObject_Unlock(object);
	    return (NSSTrust *)NULL;
	}
	if (rvt->serverAuth == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->serverAuth = serverAuth;
	}
	if (rvt->clientAuth == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->clientAuth = clientAuth;
	}
	if (rvt->emailProtection == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->emailProtection = emailProtection;
	}
	if (rvt->codeSigning == nssTrustLevel_Unknown ||
	    myTrustOrder < lastTrustOrder) 
	{
	    rvt->codeSigning = codeSigning;
	}
	rvt->stepUpApproved = stepUp;
	lastTrustOrder = myTrustOrder;
    }
    nssPKIObject_Unlock(object);
    return rvt;
}