*Thanks for the quick answer*, actually command line is good as it would be done in a child process using a secure vault for password creation that no admin knows anyway or makes up. No human is involved is always the best solution. Can't trust those humans.
thanks. I enclosed the correct code solution below for anyone to see how to programmatically create an OSCP request. ./OCSPrequest -help Usage: ./OCSPrequest <cert> <issuer root> eg: ./OCSPrequest 1000.pem ./demoCA/cacert.pem OCSPrequest.c ============ /** * cc -o OCSPrequest -Wno-deprecated-declarations -Wno-pointer-type-mismatch OCSPrequest.c -lcrypto * * * Origin: r redpath * * * The fields in this structure are as follows: * * typedef struct { * char *url; * X509 *cert; * X509 *issuer; * spc_x509store_t *store; * X509 *sign_cert; * EVP_PKEY *sign_key; * long skew; * long maxage; * } spc_ocsprequest_t; * * url * Address of the OCSP responder to which to connect; this should always be a * URL that specifies either HTTP or HTTPS as the service. For example, * VeriSign's OCSP responder address is http://ocsp.verisign.com. * * cert * Pointer to the certificate whose revocation status you want to check. * In many cases, this will likely come from the peer when establishing or * renegotiating an SSL session. * * issuer * Pointer to the certificate that issued the certificate whose revocation * status you want to check. This should be a trusted root certificate. * * store * Any information required for building an X509_STORE object internally. * This object will be used for verifying the OCSP responder's certificate. * A full discussion of this object can be found in Recipe 10.5, but basically * it contains trusted certificates and CRLs that OpenSSL can use to verify * the validity of the certificate received from the OCSP responder. * * sign_cert * An OCSP request can optionally be signed. Some servers require signed * requests. Any server will accept a signed request provided that the server * is able to verify the signature. If you want the request to be signed, * this field should be non-NULL and should be a pointer to the certificate * to use to sign the request. If you are going to sign your request, you * should use a certificate that has been issued by a CA that is trusted by * the OCSP responder so that the responder will be able to verify its validity. * * sign_key * If the sign_cert member is non-NULL, this member must be filled in with * a pointer to the private key to use in signing the request. It is ignored * if the sign_cert member is NULL. * * skew * An OCSP response contains three time fields: thisUpdate, nextUpdate, and * producedAt. These fields must be checked to determine how reliable the * results from the responder are. For example, under no circumstance should * thisUpdate ever be greater than nextUpdate. However, it is likely that there * will be some amount of clock skew between the server and the client. skew * defines an acceptable amount of skew in units of seconds. It should be set * <to a reasonably low value. In most cases, five seconds should work out fine. * * maxage * RFC 2560 OCSP responders are allowed to precompute responses to improve response * time by eliminating the need to sign a response for every request. There are * obvious security implications if a server opts to do this, as we discussed in * Recipe 10.1. The producedAt field in the response will contain the time at which * the response was computed, whether or not it was precomputed. The maxage member * specifies the maximum age in seconds of responses that should be considered * acceptable. Setting maxage to 0 will effectively cause the producedAt field in * the response to be ignored and any otherwise acceptable response to be accepted, * regardless of its age. OpenSSL's command-line ocsp command defaults to ignoring * the producedAt field. However, we think it is too risky to accept precomputed * responses. Unfortunately, there is no way to completely disable the acceptance * of precomputed responses. The closest we can get is to set this value to one * second, which is what we recommend you do. * Querying an OCSP responder is actually a complex operation, even though we are * effectively reducing the amount of work necessary for you to a single function * call. Because of the complexity of the operation, a number of things can go wrong, * and so we have defined a sizable number of possible error codes. In some cases, * we have lumped a number of finer-grained errors into a single error code, but * the code presented here can easily be expanded to provide more detailed error * information. * ************************/ #include <time.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/ocsp.h> #include <openssl/bio.h> #include <openssl/ssl.h> #include <openssl/pem.h> #include <openssl/conf.h> #include <openssl/x509v3.h> #ifndef OPENSSL_NO_ENGINE #include <openssl/engine.h> #endif #define SPC_X509STORE_NO_DEFAULT_CAFILE 0x01 #define SPC_X509STORE_NO_DEFAULT_CAPATH 0x02 typedef int (*spc_x509verifycallback_t)(int, X509_STORE_CTX *); typedef struct { char *cafile; char *capath; char *crlfile; spc_x509verifycallback_t callback; STACK_OF(X509) *certs; STACK_OF(X509_CRL) *crls; char *use_certfile; STACK_OF(X509) *use_certs; char *use_keyfile; EVP_PKEY *use_key; int flags; } spc_x509store_t; typedef struct { char *url; X509 *cert; X509 *issuer; spc_x509store_t *store; X509 *sign_cert; EVP_PKEY *sign_key; long skew; long maxage; } spc_ocsprequest_t; typedef enum { SPC_OCSPRESULT_ERROR_INVALIDRESPONSE = -12, SPC_OCSPRESULT_ERROR_CONNECTFAILURE = -11, SPC_OCSPRESULT_ERROR_SIGNFAILURE = -10, SPC_OCSPRESULT_ERROR_BADOCSPADDRESS = -9, SPC_OCSPRESULT_ERROR_OUTOFMEMORY = -8, SPC_OCSPRESULT_ERROR_UNKNOWN = -7, SPC_OCSPRESULT_ERROR_UNAUTHORIZED = -6, SPC_OCSPRESULT_ERROR_SIGREQUIRED = -5, SPC_OCSPRESULT_ERROR_TRYLATER = -3, SPC_OCSPRESULT_ERROR_INTERNALERROR = -2, SPC_OCSPRESULT_ERROR_MALFORMEDREQUEST = -1, SPC_OCSPRESULT_CERTIFICATE_VALID = 0, SPC_OCSPRESULT_CERTIFICATE_REVOKED = 1 } spc_ocspresult_t; /** * */ void spc_init_x509store(spc_x509store_t *spc_store) { spc_store->cafile = 0; spc_store->capath = 0; spc_store->crlfile = 0; spc_store->callback = 0; spc_store->certs = sk_X509_new_null( ); spc_store->crls = sk_X509_CRL_new_null( ); spc_store->use_certfile = 0; spc_store->use_certs = sk_X509_new_null( ); spc_store->use_keyfile = 0; spc_store->use_key = 0; spc_store->flags = 0; } /** * */ void spc_cleanup_x509store(spc_x509store_t *spc_store) { if (spc_store->cafile) free(spc_store->cafile); if (spc_store->capath) free(spc_store->capath); if (spc_store->crlfile) free(spc_store->crlfile); if (spc_store->use_certfile) free(spc_store->use_certfile); if (spc_store->use_keyfile) free(spc_store->use_keyfile); if (spc_store->use_key) EVP_PKEY_free(spc_store->use_key); sk_X509_free(spc_store->certs); sk_X509_free(spc_store->crls); sk_X509_free(spc_store->use_certs); } /** * */ X509_STORE *spc_create_x509store(spc_x509store_t *spc_store) { int i; X509_STORE *store; X509_LOOKUP *lookup; store = X509_STORE_new( ); /** if (spc_store->callback) X509_STORE_set_verify_cb_func(store, spc_store->callback); else X509_STORE_set_verify_cb_func(store, spc_verify_callback); **/ if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file( )))) goto error_exit; if (!spc_store->cafile) { printf("no CAFILE \n"); if (!(spc_store->flags & SPC_X509STORE_NO_DEFAULT_CAFILE)) X509_LOOKUP_load_file(lookup, 0, X509_FILETYPE_DEFAULT); } else{ if (!X509_LOOKUP_load_file(lookup, spc_store->cafile, X509_FILETYPE_PEM)) goto error_exit; } if (spc_store->crlfile) { if (!X509_load_crl_file(lookup, spc_store->crlfile, X509_FILETYPE_PEM)) goto error_exit; X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir( )))) goto error_exit; if (!spc_store->capath) { if (!(spc_store->flags & SPC_X509STORE_NO_DEFAULT_CAPATH)) X509_LOOKUP_add_dir(lookup, 0, X509_FILETYPE_DEFAULT); } else if (!X509_LOOKUP_add_dir(lookup, spc_store->capath, X509_FILETYPE_PEM)) goto error_exit; for (i = 0; i < sk_X509_num(spc_store->certs); i++) if (!X509_STORE_add_cert(store, sk_X509_value(spc_store->certs, i))) goto error_exit; for (i = 0; i < sk_X509_CRL_num(spc_store->crls); i++) if (!X509_STORE_add_crl(store, sk_X509_CRL_value(spc_store->crls, i))) goto error_exit; // printf("success spc_create_x509store\n"); return store; error_exit: printf("error_exit spc_create_x509store\n"); if (store) X509_STORE_free(store); return 0; } /** * */ BIO *spc_connect(char *host, int port, int ssl, spc_x509store_t *spc_store, SSL_CTX **ctx) { BIO *conn; /** SSL *ssl_ptr; if (ssl) { if (!(conn = spc_connect_ssl(host, port, spc_store, ctx))) goto error_exit; BIO_get_ssl(conn, &ssl_ptr); if (!spc_verify_cert_hostname(SSL_get_peer_certificate(ssl_ptr), host)) goto error_exit; if (SSL_get_verify_result(ssl_ptr) != X509_V_OK) goto error_exit; return conn; } **/ *ctx = 0; if (!(conn = BIO_new_connect(host))) goto error_exit; BIO_set_conn_int_port(conn, &port); if (BIO_do_connect(conn) <= 0) goto error_exit; return conn; error_exit: printf("error_exit connect\n"); if (conn) BIO_free_all(conn); return 0; } /** * */ spc_ocspresult_t spc_verify_via_ocsp(spc_ocsprequest_t *data) { BIO *bio = 0; int rc, reason, ssl, status; char *host = 0, *path = 0, *port = 0; SSL_CTX *ctx = 0; X509_STORE *store = 0; OCSP_CERTID *id; OCSP_REQUEST *req = 0; OCSP_RESPONSE *resp = 0; OCSP_BASICRESP *basic = 0; spc_ocspresult_t result; ASN1_GENERALIZEDTIME *producedAt, *thisUpdate, *nextUpdate; result = SPC_OCSPRESULT_ERROR_UNKNOWN; if (!OCSP_parse_url(data->url, &host, &port, &path, &ssl)) { result = SPC_OCSPRESULT_ERROR_BADOCSPADDRESS; goto end; } if (!(req = OCSP_REQUEST_new( ))) { result = SPC_OCSPRESULT_ERROR_OUTOFMEMORY; goto end; } // //Here I guess is where you can add multiple certs" Right now we haev only one // id = OCSP_cert_to_id(0, data->cert, data->issuer); if (!id || !OCSP_request_add0_id(req, id)) goto end; //lets do it twice what the heck //show how to do multiple x509s // id = OCSP_cert_to_id(0, data->cert, data->issuer); // if (!id || !OCSP_request_add0_id(req, id)) goto end; OCSP_request_add1_nonce(req, 0, -1); /* sign the request */ if (data->sign_cert && data->sign_key && !OCSP_request_sign(req, data->sign_cert, data->sign_key, EVP_sha1( ), 0, 0)) { result = SPC_OCSPRESULT_ERROR_SIGNFAILURE; goto end; } /* establish a connection to the OCSP responder */ if (!(bio = spc_connect(host, atoi(port), ssl, data->store, &ctx))) { result = SPC_OCSPRESULT_ERROR_CONNECTFAILURE; goto end; } /* send the request and get a response */ resp = OCSP_sendreq_bio(bio, path, req); if (resp==NULL) goto end; if ((rc = OCSP_response_status(resp)) != OCSP_RESPONSE_STATUS_SUCCESSFUL) { switch (rc) { case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: result = SPC_OCSPRESULT_ERROR_MALFORMEDREQUEST; break; case OCSP_RESPONSE_STATUS_INTERNALERROR: result = SPC_OCSPRESULT_ERROR_INTERNALERROR; break; case OCSP_RESPONSE_STATUS_TRYLATER: result = SPC_OCSPRESULT_ERROR_TRYLATER; break; case OCSP_RESPONSE_STATUS_SIGREQUIRED: result = SPC_OCSPRESULT_ERROR_SIGREQUIRED; break; case OCSP_RESPONSE_STATUS_UNAUTHORIZED: result = SPC_OCSPRESULT_ERROR_UNAUTHORIZED; break; } goto end; } /* verify the response */ result = SPC_OCSPRESULT_ERROR_INVALIDRESPONSE; if (!(basic = OCSP_response_get1_basic(resp))) goto end; if (OCSP_check_nonce(req, basic) <= 0) goto end; if (data->store && !(store = spc_create_x509store(data->store))) goto end; printf("verify signature\n"); //verify signature if ((rc = OCSP_basic_verify(basic, 0, store, 0)) <= 0) goto end; if (!OCSP_resp_find_status(basic, id, &status, &reason, &producedAt, &thisUpdate, &nextUpdate)){ printf("verify signature failed\n"); goto end; } if (!OCSP_check_validity(thisUpdate, nextUpdate, data->skew, data->maxage)) goto end; /* All done. Set the return code based on the status from the response. */ if (status == V_OCSP_CERTSTATUS_REVOKED) result = SPC_OCSPRESULT_CERTIFICATE_REVOKED; else result = SPC_OCSPRESULT_CERTIFICATE_VALID; end: if (bio) BIO_free_all(bio); if (host) OPENSSL_free(host); if (port) OPENSSL_free(port); if (path) OPENSSL_free(path); if (req) OCSP_REQUEST_free(req); if (resp) OCSP_RESPONSE_free(resp); if (basic) OCSP_BASICRESP_free(basic); // if (ctx) SSL_CTX_free(ctx); if (store) X509_STORE_free(store); return result; } void help(){ printf("\nUsage:\n"); printf(" ./OCSPrequest <cert> <issuer root>\n"); printf("eg:\n"); printf(" ./OCSPrequest 1000.pem ./demoCA/cacert.pem\n\n"); exit(0); } /** * */ int main(int argc, char **argv){ char *url= "http://127.0.0.1:8082"; //For now our OCSP server location char *x509file="./demoCA/newcerts/1000.pem"; //The x509 filename we want to verify char *inCAcert="./demoCA/cacert.pem"; X509 *x=NULL; X509 *issuerRoot=NULL; switch (argc){ case 1: //defaults break; case 3: x509file= argv[1]; inCAcert= argv[2]; break; default: help(); } printf("\nOCSP URL: %s\n",url); printf("Cert checking: %s\n",x509file); printf("Root issuer: %s\n\n",inCAcert); ERR_load_BIO_strings(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); //Load the X509 file // FILE *fp =fopen(x509file, "rb"); if (fp==NULL) { printf("X509 File not found %s which is to be verified\n",x509file); return 1; } x= PEM_read_X509(fp,&x, NULL, NULL); if (x==NULL){ fprintf(stderr,"null x509\n"); return 1; } fclose(fp); //Load the X509 file // fp =fopen("./demoCA/cacert.pem", "rb"); if (fp==NULL) { printf("X509 File not found %s which is to be verified\n",x509file); return 1; } issuerRoot= PEM_read_X509(fp,&issuerRoot, NULL, NULL); if (issuerRoot==NULL){ fprintf(stderr,"null x509 issuer Root\n"); return 1; } fclose(fp); /** typedef struct { char *url; X509 *cert; X509 *issuer; spc_x509store_t *store; X509 *sign_cert; EVP_PKEY *sign_key; long skew; long maxage; } spc_ocsprequest_t; **/ spc_ocsprequest_t *req= malloc(sizeof (spc_ocsprequest_t)); req->url = url; req->cert = x; req->issuer = issuerRoot; req->store = malloc(sizeof(spc_x509store_t) ); spc_init_x509store(req->store); req->store->cafile= inCAcert; req->sign_cert= NULL; //OCSP request is not optionally signed req->sign_key = NULL; req->skew = 5; //5 seconds req->maxage = 1; //recommended to set to one spc_ocspresult_t result= spc_verify_via_ocsp(req); switch (result){ case 0: printf("Verify result GOOD\n"); break; case 1: printf("Verify result REVOKED\n"); default: printf("ERROR Verify result is %d \n",result); break; } return 0; } -- View this message in context: http://openssl.6102.n7.nabble.com/OSCP-request-tp45835p45889.html Sent from the OpenSSL - User mailing list archive at Nabble.com. ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org