static int __pmCertificateTimestamp(SECItem *vtime, char *buffer, size_t size) { PRExplodedTime exploded; SECStatus secsts; int64 itime; switch (vtime->type) { case siUTCTime: secsts = DER_UTCTimeToTime(&itime, vtime); break; case siGeneralizedTime: secsts = DER_GeneralizedTimeToTime(&itime, vtime); break; default: return -EINVAL; } if (secsts != SECSuccess) return __pmSecureSocketsError(PR_GetError()); /* Convert to local time */ PR_ExplodeTime(itime, PR_GMTParameters, &exploded); if (!PR_FormatTime(buffer, size, "%a %b %d %H:%M:%S %Y", &exploded)) return __pmSecureSocketsError(PR_GetError()); return 0; }
SECStatus CERT_FindInvalidDateExten (CERTCrl *crl, int64 *value) { SECItem encodedExtenValue; SECItem decodedExtenValue = {siBuffer,0}; SECStatus rv; encodedExtenValue.data = decodedExtenValue.data = NULL; encodedExtenValue.len = decodedExtenValue.len = 0; rv = cert_FindExtension (crl->extensions, SEC_OID_X509_INVALID_DATE, &encodedExtenValue); if ( rv != SECSuccess ) return (rv); rv = SEC_ASN1DecodeItem (NULL, &decodedExtenValue, SEC_ASN1_GET(SEC_GeneralizedTimeTemplate), &encodedExtenValue); if (rv == SECSuccess) rv = DER_GeneralizedTimeToTime(value, &encodedExtenValue); PORT_Free (decodedExtenValue.data); PORT_Free (encodedExtenValue.data); return (rv); }
SECStatus sv_PrintInvalidDateExten(FILE *out, SECItem *value, char *msg) { SECItem decodedValue; SECStatus rv; PRTime invalidTime; char *formattedTime = NULL; decodedValue.data = NULL; rv = SEC_ASN1DecodeItem(NULL, &decodedValue, SEC_ASN1_GET(SEC_GeneralizedTimeTemplate), value); if (rv == SECSuccess) { rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue); if (rv == SECSuccess) { formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y"); fprintf(out, "%s: %s\n", msg, formattedTime); PORT_Free(formattedTime); } } PORT_Free(decodedValue.data); return (rv); }
int main() { SECItem badTime; PRTime prtime; SECStatus rv; int error; PRBool failed = PR_FALSE; /* A UTCTime string with an embedded null. */ badTime.type = siBuffer; badTime.data = (unsigned char *)"091219000000Z\0junkjunkjunkjunkjunkjunk"; badTime.len = 38; rv = DER_UTCTimeToTime(&prtime, &badTime); if (rv == SECSuccess) { fprintf(stderr, "DER_UTCTimeToTime should have failed but " "succeeded\n"); failed = PR_TRUE; } else { error = PORT_GetError(); if (error != SEC_ERROR_INVALID_TIME) { fprintf(stderr, "DER_UTCTimeToTime failed with error %d, " "expected error %d\n", error, SEC_ERROR_INVALID_TIME); failed = PR_TRUE; } } /* A UTCTime string with junk after a valid date/time. */ badTime.type = siBuffer; badTime.data = (unsigned char *)"091219000000Zjunk"; badTime.len = 17; rv = DER_UTCTimeToTime(&prtime, &badTime); if (rv == SECSuccess) { fprintf(stderr, "DER_UTCTimeToTime should have failed but " "succeeded\n"); failed = PR_TRUE; } else { error = PORT_GetError(); if (error != SEC_ERROR_INVALID_TIME) { fprintf(stderr, "DER_UTCTimeToTime failed with error %d, " "expected error %d\n", error, SEC_ERROR_INVALID_TIME); failed = PR_TRUE; } } /* A GeneralizedTime string with an embedded null. */ badTime.type = siBuffer; badTime.data = (unsigned char *)"20091219000000Z\0junkjunkjunkjunkjunkjunk"; badTime.len = 40; rv = DER_GeneralizedTimeToTime(&prtime, &badTime); if (rv == SECSuccess) { fprintf(stderr, "DER_GeneralizedTimeToTime should have failed but " "succeeded\n"); failed = PR_TRUE; } else { error = PORT_GetError(); if (error != SEC_ERROR_INVALID_TIME) { fprintf(stderr, "DER_GeneralizedTimeToTime failed with error %d, " "expected error %d\n", error, SEC_ERROR_INVALID_TIME); failed = PR_TRUE; } } /* A GeneralizedTime string with junk after a valid date/time. */ badTime.type = siBuffer; badTime.data = (unsigned char *)"20091219000000Zjunk"; badTime.len = 19; rv = DER_GeneralizedTimeToTime(&prtime, &badTime); if (rv == SECSuccess) { fprintf(stderr, "DER_GeneralizedTimeToTime should have failed but " "succeeded\n"); failed = PR_TRUE; } else { error = PORT_GetError(); if (error != SEC_ERROR_INVALID_TIME) { fprintf(stderr, "DER_GeneralizedTimeToTime failed with error %d, " "expected error %d\n", error, SEC_ERROR_INVALID_TIME); failed = PR_TRUE; } } if (failed) { fprintf(stderr, "FAIL\n"); return 1; } printf("PASS\n"); return 0; }
/* * FUNCTION: pkix_pl_OcspResponse_VerifySignature * DESCRIPTION: * * This function verifies the ocspResponse signature field in the OcspResponse * pointed to by "response", storing PKIX_TRUE at "pPassed" if verification * is successful and PKIX_FALSE otherwise. If verification is unsuccessful an * error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode. * * PARAMETERS * "response" * The address of the OcspResponse whose signature field is to be * retrieved. Must be non-NULL. * "cert" * The address of the Cert for which the OCSP query was made. Must be * non-NULL. * "procParams" * Address of ProcessingParams used to initialize the ExpirationChecker * and TargetCertChecker. Must be non-NULL. * "pPassed" * Address at which the Boolean result is stored. Must be non-NULL. * "pNBIOContext" * Address at which the NBIOContext is stored indicating whether the * checking is complete. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns an OcspResponse Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_OcspResponse_VerifySignature( PKIX_PL_OcspResponse *response, PKIX_PL_Cert *cert, PKIX_ProcessingParams *procParams, PKIX_Boolean *pPassed, void **pNBIOContext, void *plContext) { SECStatus rv = SECFailure; CERTOCSPResponse *nssOCSPResponse = NULL; CERTCertificate *issuerCert = NULL; PKIX_BuildResult *buildResult = NULL; void *nbio = NULL; void *state = NULL; ocspSignature *signature = NULL; ocspResponseData *tbsData = NULL; SECItem *tbsResponseDataDER = NULL; PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature"); PKIX_NULLCHECK_FOUR(response, cert, pPassed, pNBIOContext); nbio = *pNBIOContext; *pNBIOContext = NULL; nssOCSPResponse = response->nssOCSPResponse; if (nssOCSPResponse == NULL) { PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); goto cleanup; } tbsData = ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER); signature = ocsp_GetResponseSignature(nssOCSPResponse); /* Are we resuming after a WOULDBLOCK response? */ if (nbio == NULL) { /* No, this is a new query */ issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(), certUsageAnyCA); /* * If this signature has already gone through verification, * just return the cached result. */ if (signature->wasChecked) { if (signature->status == SECSuccess) { response->signerCert = CERT_DupCertificate(signature->cert); } else { PORT_SetError(signature->failureReason); goto cleanup; } } response->signerCert = ocsp_GetSignerCertificate(response->handle, tbsData, signature, issuerCert); if (response->signerCert == NULL) { PORT_SetError(SEC_ERROR_UNKNOWN_SIGNER); goto cleanup; } PKIX_CHECK( PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert, &(response->pkixSignerCert), plContext), PKIX_CERTCREATEWITHNSSCERTFAILED); /* * We could mark this true at the top of this function, or * always below at "finish", but if the problem was just that * we could not find the signer's cert, leave that as if the * signature hasn't been checked. Maybe a subsequent call will * have better luck. */ signature->wasChecked = PR_TRUE; /* * We are about to verify the signer certificate; we need to * specify *when* that certificate must be valid -- for our * purposes we expect it to be valid when the response was * signed. The value of "producedAt" is the signing time. */ rv = DER_GeneralizedTimeToTime(&response->producedAt, &tbsData->producedAt); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); goto cleanup; } /* * We need producedAtDate and pkixSignerCert if we are calling a * user-supplied verification function. Let's put their * creation before the code that gets repeated when * non-blocking I/O is used. */ PKIX_CHECK( pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt, &(response->producedAtDate), plContext), PKIX_DATECREATEFROMPRTIMEFAILED); } /* * Just because we have a cert does not mean it is any good; check * it for validity, trust and usage. Use the caller-supplied * verification function, if one was supplied. */ if (ocsp_CertIsOCSPDefaultResponder(response->handle, response->signerCert)) { rv = SECSuccess; } else { SECCertUsage certUsage; if (CERT_IsCACert(response->signerCert, NULL)) { certUsage = certUsageAnyCA; } else { certUsage = certUsageStatusResponder; } PKIX_CHECK_ONLY_FATAL( pkix_pl_OcspResponse_VerifyResponse(response, procParams, certUsage, &state, &buildResult, &nbio, plContext), PKIX_CERTVERIFYKEYUSAGEFAILED); if (pkixTempErrorReceived) { rv = SECFailure; goto cleanup; } if (nbio != NULL) { *pNBIOContext = nbio; goto cleanup; } } rv = ocsp_VerifyResponseSignature(response->signerCert, signature, tbsResponseDataDER, NULL); cleanup: if (rv == SECSuccess) { *pPassed = PKIX_TRUE; } else { *pPassed = PKIX_FALSE; } if (signature) { if (signature->wasChecked) { signature->status = rv; } if (rv != SECSuccess) { signature->failureReason = PORT_GetError(); if (response->signerCert != NULL) { CERT_DestroyCertificate(response->signerCert); response->signerCert = NULL; } } else { /* Save signer's certificate in signature. */ signature->cert = CERT_DupCertificate(response->signerCert); } } if (issuerCert) CERT_DestroyCertificate(issuerCert); PKIX_RETURN(OCSPRESPONSE); }