📄 ocsp.c
字号:
if (sigdata.ptr == NULL) return empty_chunk; /* include our certificate */ pos = build_asn1_explicit_object(&certs, ASN1_CONTEXT_C_0 , ASN1_SEQUENCE, ocsp_requestor_cert->certificate.len); chunkcpy(pos, ocsp_requestor_cert->certificate); /* build signature comprising algorithm, signature and cert */ pos = build_asn1_explicit_object(&signature, ASN1_CONTEXT_C_0 , ASN1_SEQUENCE , sizeof(ASN1_sha1WithRSA_id) + sigdata.len + certs.len); constcpy( pos, ASN1_sha1WithRSA_id); mv_chunk(&pos, sigdata); mv_chunk(&pos, certs); return signature;}/* * build requestCert (into Request) */static chunk_tbuild_req_cert(ocsp_location_t *location, ocsp_certinfo_t *certinfo){ chunk_t reqCert; chunk_t issuerNameHash, issuerKeyHash, serialNumber; u_char *pos; /* build content */ /* issuer_name_hash */ pos = build_asn1_object(&issuerNameHash, ASN1_OCTET_STRING , location->authNameID.len); chunkcpy(pos, location->authNameID); /* issuer_key_hash */ pos = build_asn1_object(&issuerKeyHash, ASN1_OCTET_STRING , location->authKeyID.len); chunkcpy(pos, location->authKeyID); /* serial number */ pos = build_asn1_object(&serialNumber, ASN1_INTEGER , certinfo->serialNumber.len); chunkcpy(pos, certinfo->serialNumber); /* assembly */ pos = build_asn1_object(&reqCert, ASN1_SEQUENCE , sizeof(ASN1_sha1_id) + issuerNameHash.len + issuerKeyHash.len + serialNumber.len); constcpy( pos, ASN1_sha1_id); mv_chunk(&pos, issuerNameHash); mv_chunk(&pos, issuerKeyHash); mv_chunk(&pos, serialNumber); return reqCert;}/* * build request (into requestList) */static chunk_tbuild_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo){ /* build request - no singleRequestExtensions used */ chunk_t request, reqCert; u_char *pos; /* build content */ reqCert = build_req_cert(location, certinfo); pos = build_asn1_object(&request, ASN1_SEQUENCE , reqCert.len); mv_chunk(&pos, reqCert); return request;}/* * build requestList (into TBSRequest) */static chunk_tbuild_request_list(ocsp_location_t *location){ chunk_t requestList; request_list_t *reqs = NULL; ocsp_certinfo_t *certinfo = location->certinfo; u_char *pos; size_t datalen = 0; /* build content */ while (certinfo != NULL) { /* build request for every certificate in list * and store them in a chained list */ request_list_t *req = alloc_thing(request_list_t, "ocsp request"); req->request = build_request(location, certinfo); req->next = reqs; reqs = req; datalen += req->request.len; certinfo = certinfo->next; } pos = build_asn1_object(&requestList, ASN1_SEQUENCE , datalen); /* copy all in chained list, free list afterwards */ while (reqs != NULL) { request_list_t *req = reqs; mv_chunk(&pos, req->request); reqs = reqs->next; pfree(req); } return requestList;}/* * build requestorName (into TBSRequest) */static chunk_tbuild_requestor_name(void){ chunk_t reqName; u_char *pos; pos = build_asn1_explicit_object(&reqName, ASN1_CONTEXT_C_1 , ASN1_CONTEXT_C_4, ocsp_requestor_cert->subject.len); chunkcpy(pos, ocsp_requestor_cert->subject); return reqName;}/* * build nonce extension (into requestExtensions) */static chunk_tbuild_nonce_extension(ocsp_location_t *location){ chunk_t nonce, content; u_char *pos; /* generate a random nonce */ pos = build_asn1_object(&content, ASN1_OCTET_STRING , NONCE_LENGTH); get_rnd_bytes(pos, NONCE_LENGTH); clonetochunk(location->nonce, pos, NONCE_LENGTH, "ocsp nonce"); pos = build_asn1_object(&nonce, ASN1_SEQUENCE , sizeof(ASN1_nonce_oid) + content.len); constcpy( pos, ASN1_nonce_oid); mv_chunk(&pos, content); return nonce;}/* * build acceptable response types extension (into requestExtensions) */static chunk_tbuild_accept_extension(void){ chunk_t acceptExt, content; u_char *pos; /* content is a sequence of OIDs in an octet string * in our case only BasicOCSPResponse */ clonetochunk(content, ASN1_response_content, sizeof(ASN1_response_content) , "clone"); pos = build_asn1_object(&acceptExt, ASN1_SEQUENCE , sizeof(ASN1_response_oid) + content.len); constcpy( pos, ASN1_response_oid); mv_chunk(&pos, content); return acceptExt;}/* * build requestExtensions (into TBSRequest) */static chunk_tbuild_request_ext(ocsp_location_t *location){ chunk_t requestExt; chunk_t nonceExt, acceptTypes; u_char *pos; /* build content */ nonceExt = build_nonce_extension(location); acceptTypes = build_accept_extension(); pos = build_asn1_explicit_object(&requestExt, ASN1_CONTEXT_C_2 , ASN1_SEQUENCE, nonceExt.len + acceptTypes.len); mv_chunk(&pos, nonceExt); mv_chunk(&pos, acceptTypes); return requestExt;}/* * build TBSRequest (into OCSPRequest) */static chunk_tbuild_tbs_request(ocsp_location_t *location, bool has_requestor_cert){ chunk_t tbsRequest; chunk_t requestList, requestorName, requestExt; u_char *pos; /* build content */ /* version is skipped since the default is ok */ requestorName = (has_requestor_cert)? build_requestor_name() : empty_chunk; requestList = build_request_list(location); requestExt = build_request_ext(location); pos = build_asn1_object(&tbsRequest, ASN1_SEQUENCE , requestList.len + requestorName.len + requestExt.len); mv_chunk(&pos, requestorName); mv_chunk(&pos, requestList); mv_chunk(&pos, requestExt); return tbsRequest;}/* assembles an ocsp request to given location * and sets nonce field in location to the sent nonce */chunk_tbuild_ocsp_request(ocsp_location_t *location){ bool has_requestor_cert; chunk_t request, tbsRequest, signature; char buf[BUF_LEN]; u_char *pos; DBG(DBG_CONTROL, DBG_log("assembling ocsp request"); dntoa(buf, BUF_LEN, location->issuer); DBG_log("issuer: '%s'", buf); if (location->authKeyID.ptr != NULL) { datatot(location->authKeyID.ptr, location->authKeyID.len, ':' , buf, BUF_LEN); DBG_log("authkey: %s", buf); } ) lock_certs_and_keys("build_ocsp_request"); /* looks for requestor cert and matching private key */ has_requestor_cert = get_ocsp_requestor_cert(location); /* build content */ tbsRequest = build_tbs_request(location, has_requestor_cert); /* sign tbsReuqest */ signature = (has_requestor_cert)? build_signature(tbsRequest) : empty_chunk; unlock_certs_and_keys("build_ocsp_request"); /* build ocsp request */ pos = build_asn1_object(&request, ASN1_SEQUENCE , tbsRequest.len + signature.len); mv_chunk(&pos, tbsRequest); mv_chunk(&pos, signature); return request;}/* * check if the OCSP response has a valid signature */static boolvalid_ocsp_response(response_t *res){ int pathlen; x509cert_t *authcert; lock_authcert_list("valid_ocsp_response"); authcert = get_authcert(res->responder_id_name, empty_chunk , res->responder_id_key, AUTH_OCSP | AUTH_CA); if (authcert == NULL) { plog("no matching ocsp signer cert found"); unlock_authcert_list("valid_ocsp_response"); return FALSE; } DBG(DBG_CONTROL, DBG_log("ocsp signer cert found") ) if (!check_signature(res->tbs, res->signature, res->algorithm, authcert)) { plog("signature of ocsp response is invalid"); unlock_authcert_list("valid_ocsp_response"); return FALSE; } DBG(DBG_CONTROL, DBG_log("signature of ocsp response is valid") ) for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { u_char buf[BUF_LEN]; err_t ugh = NULL; time_t until; x509cert_t *cert = authcert; DBG(DBG_CONTROL, dntoa(buf, BUF_LEN, cert->subject); DBG_log("subject: '%s'",buf); dntoa(buf, BUF_LEN, cert->issuer); DBG_log("issuer: '%s'",buf); if (cert->authKeyID.ptr != NULL) { datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' , buf, BUF_LEN); DBG_log("authkey: %s", buf); } ) ugh = check_validity(authcert, &until); if (ugh != NULL) { plog("%s", ugh); unlock_authcert_list("valid_ocsp_response"); return FALSE; } DBG(DBG_CONTROL, DBG_log("certificate is valid") ) authcert = get_authcert(cert->issuer, cert->authKeySerialNumber , cert->authKeyID, AUTH_CA); if (authcert == NULL) { plog("issuer cacert not found"); unlock_authcert_list("valid_ocsp_response"); return FALSE; } DBG(DBG_CONTROL, DBG_log("issuer cacert found") ) if (!check_signature(cert->tbsCertificate, cert->signature, cert->algorithm, authcert)) { plog("certificate signature is invalid"); unlock_authcert_list("valid_ocsp_response"); return FALSE; } DBG(DBG_CONTROL, DBG_log("certificate signature is valid") ) /* check if cert is self-signed */ if (same_dn(cert->issuer, cert->subject)) { DBG(DBG_CONTROL, DBG_log("reached self-signed root ca") ) unlock_authcert_list("valid_ocsp_response"); return TRUE; } } plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); unlock_authcert_list("valid_ocsp_response"); return FALSE;}/* * parse a basic OCSP response */static boolparse_basic_ocsp_response(chunk_t blob, int level0, response_t *res){ u_int level, version, extn_oid = 0; u_char buf[BUF_LEN]; asn1_ctx_t ctx; bool critical; chunk_t object; int objectID = 0; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < BASIC_RESPONSE_ROOF) { if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx)) return FALSE; switch (objectID) { case BASIC_RESPONSE_TBS_DATA: res->tbs = object; break; case BASIC_RESPONSE_VERSION: version = (object.len)? (1 + (u_int)*object.ptr) : 1; if (version != OCSP_BASIC_RESPONSE_VERSION) { plog("wrong ocsp basic response version (version= %i)", version); return FALSE; } break; case BASIC_RESPONSE_ID_BY_NAME: res->responder_id_name = object; DBG(DBG_PARSING, dntoa(buf, BUF_LEN, object); DBG_log(" '%s'",buf) ) break; case BASIC_RESPONSE_ID_BY_KEY: res->responder_id_key = object; break; case BASIC_RESPONSE_PRODUCED_AT: res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME); break; case BASIC_RESPONSE_RESPONSES: res->responses = object; break; case BASIC_RESPONSE_EXT_ID:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -