int TS_REQ_print_bio(BIO *bio, TS_REQ *a) { int v; ASN1_OBJECT *policy_id; const ASN1_INTEGER *nonce; if (a == NULL) return 0; v = TS_REQ_get_version(a); BIO_printf(bio, "Version: %d\n", v); TS_MSG_IMPRINT_print_bio(bio, TS_REQ_get_msg_imprint(a)); BIO_printf(bio, "Policy OID: "); policy_id = TS_REQ_get_policy_id(a); if (policy_id == NULL) BIO_printf(bio, "unspecified\n"); else TS_OBJ_print_bio(bio, policy_id); BIO_printf(bio, "Nonce: "); nonce = TS_REQ_get_nonce(a); if (nonce == NULL) BIO_printf(bio, "unspecified"); else TS_ASN1_INTEGER_print_bio(bio, nonce); BIO_write(bio, "\n", 1); BIO_printf(bio, "Certificate required: %s\n", TS_REQ_get_cert_req(a) ? "yes" : "no"); TS_ext_print_bio(bio, TS_REQ_get_exts(a)); return 1; }
TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX (TS_REQ * req, TS_VERIFY_CTX * ctx) { TS_VERIFY_CTX *ret = ctx; ASN1_OBJECT *policy; TS_MSG_IMPRINT *imprint; X509_ALGOR *md_alg; ASN1_OCTET_STRING *msg; const ASN1_INTEGER *nonce; OPENSSL_assert (req != NULL); if (ret) TS_VERIFY_CTX_cleanup (ret); else if (!(ret = TS_VERIFY_CTX_new ())) return NULL; /* Setting flags. */ ret->flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE); /* Setting policy. */ if ((policy = TS_REQ_get_policy_id (req)) != NULL) { if (!(ret->policy = OBJ_dup (policy))) goto err; } else ret->flags &= ~TS_VFY_POLICY; /* Setting md_alg, imprint and imprint_len. */ imprint = TS_REQ_get_msg_imprint (req); md_alg = TS_MSG_IMPRINT_get_algo (imprint); if (!(ret->md_alg = X509_ALGOR_dup (md_alg))) goto err; msg = TS_MSG_IMPRINT_get_msg (imprint); ret->imprint_len = ASN1_STRING_length (msg); if (!(ret->imprint = OPENSSL_malloc (ret->imprint_len))) goto err; memcpy (ret->imprint, ASN1_STRING_data (msg), ret->imprint_len); /* Setting nonce. */ if ((nonce = TS_REQ_get_nonce (req)) != NULL) { if (!(ret->nonce = ASN1_INTEGER_dup (nonce))) goto err; } else ret->flags &= ~TS_VFY_NONCE; return ret; err: if (ctx) TS_VERIFY_CTX_cleanup (ctx); else TS_VERIFY_CTX_free (ret); return NULL; }
int check_time_stamp(TS_RESP* tsResponse, X509* caCert, char* hash, UNSIGNED32 hash_size) { int result = 0; TS_REQ* tsRequest = NULL; TS_VERIFY_CTX* ctx = NULL; TS_MSG_IMPRINT* msgImprint = NULL; ASN1_OCTET_STRING* hashedMessage = NULL; int hashedMessageLength; tsRequest = get_timestamp_request(hash, hash_size, tsResponse->tst_info->nonce); msgImprint = TS_REQ_get_msg_imprint(tsRequest); hashedMessage = TS_MSG_IMPRINT_get_msg(msgImprint); hashedMessageLength = ASN1_STRING_length((ASN1_STRING*)hashedMessage); if (hashedMessageLength != (int)hash_size) { goto end; } if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(tsRequest, NULL))) { goto end; } ctx->flags |= TS_VFY_SIGNATURE; ctx->store = X509_STORE_new(); X509_STORE_add_cert(ctx->store, caCert); if (ossl_TS_RESP_verify_response(ctx, tsResponse)) { result = 1; } end: if (tsRequest != NULL) { TS_REQ_free(tsRequest); } if (ctx != NULL) { TS_VERIFY_CTX_free(ctx); } return result; }
static int openssl_ts_req_msg_imprint(lua_State*L) { TS_REQ* req = CHECK_OBJECT(1, TS_REQ, "openssl.ts_req"); if (lua_isnone(L, 2)) { TS_MSG_IMPRINT * msg = TS_REQ_get_msg_imprint(req); if (msg) { ASN1_OCTET_STRING *s = TS_MSG_IMPRINT_get_msg(msg); X509_ALGOR *a = TS_MSG_IMPRINT_get_algo(msg); PUSH_ASN1_OCTET_STRING(L, s); openssl_push_x509_algor(L, a); ASN1_OCTET_STRING_free(s); X509_ALGOR_free(a); return 2; } return 1; } else { size_t size; const char* data = luaL_checklstring(L, 2, &size); const EVP_MD* md = lua_isnoneornil(L, 3) ? EVP_get_digestbyname("sha1") : get_digest(L, 3); TS_MSG_IMPRINT *msg = TS_MSG_IMPRINT_new(); int ret = TS_MSG_IMPRINT_set_msg(msg, (unsigned char*)data, size); if (ret == 1) { X509_ALGOR* alg = X509_ALGOR_new(); X509_ALGOR_set_md(alg, md); if (ret == 1) { ret = TS_MSG_IMPRINT_set_algo(msg, alg); if (ret == 1) ret = TS_REQ_set_msg_imprint(req, msg); } X509_ALGOR_free(alg); } TS_MSG_IMPRINT_free(msg); return openssl_pushresult(L, ret); } };
UNSIGNED32 get_timestamp_response(const char* urlStr, char* hash, UNSIGNED32 hash_size, UNSIGNED32 httpTimeOut, TS_RESP** tsResponse) { UNSIGNED32 result = TINTERNALERROR; BIO* responseBio = NULL; Url* url = NULL; TS_REQ* tsRequest = NULL; BIO* requestBio = NULL; int requestHeaderLength; int requestLength; int requestContentLength; char requestHeader[2048 + 256]; char* request = NULL; void* contentBuffer = NULL; void* resultBuffer = NULL; int resultLength; TS_MSG_IMPRINT* msgImprint = NULL; ASN1_OCTET_STRING* hashedMessage = NULL; int hashedMessageLength; int httpResult; char *urlBuffer = NULL; int redirection = 0; /* Check if TS url is specified */ if (!urlStr) { goto end; } /* Get Request for timestamp */ tsRequest = get_timestamp_request(hash, hash_size, create_nonce(NONCE_LENGTH)); msgImprint = TS_REQ_get_msg_imprint(tsRequest); hashedMessage = TS_MSG_IMPRINT_get_msg(msgImprint); hashedMessageLength = ASN1_STRING_length((ASN1_STRING*)hashedMessage); if ((int)hash_size != hashedMessageLength) { goto end; } requestBio = BIO_new(BIO_s_mem()); if (requestBio == NULL) { goto end; } if (!i2d_TS_REQ_bio(requestBio, tsRequest)) { goto end; } contentBuffer = memory_alloc(BIO_number_written(requestBio)); if (contentBuffer == NULL) { goto end; } requestContentLength = BIO_read(requestBio, contentBuffer, BIO_number_written(requestBio)); /* Allocate memory buffer for timestamp server url */ urlBuffer = memory_alloc(strlen(urlStr) + 1); if (!urlBuffer) { goto end; } /* Copy TS url to allocated buffer */ strcpy(urlBuffer, urlStr); http_redirect: /* Parse and check URL */ url = parse_url(urlBuffer); if (url == NULL) { goto end; } if (strcmp(url->Scheme, "http") != 0) { goto end; } requestHeaderLength = sprintf(requestHeader, "POST %s HTTP/1.0\r\nHOST: %s\r\nPragma: no-cache\r\nContent-Type: application/timestamp-query\r\nAccept: application/timestamp-reply\r\nContent-Length: %d\r\n\r\n", urlBuffer, url->Host, requestContentLength); requestLength = requestHeaderLength + requestContentLength; request = (char*)memory_alloc(requestLength); if (request == NULL) { goto end; } memcpy(request, requestHeader, requestHeaderLength); memcpy(request + requestHeaderLength, contentBuffer, requestContentLength); httpResult = http_read(url->Host, request, requestLength, url->Port, httpTimeOut, 1, &resultBuffer, &resultLength); if (httpResult == HTTP_REDIRECTION && (resultBuffer) && !redirection) { free_url(url); url = NULL; memory_free(request); request = NULL; /* Allocated buffer for redirected url */ urlBuffer = memory_realloc(urlBuffer, resultLength); if (!urlBuffer) { goto end; } memcpy(urlBuffer, resultBuffer, resultLength); memory_free(resultBuffer); redirection++; goto http_redirect; } else if ((httpResult == HTTP_NOERROR) && (resultBuffer)) { responseBio = BIO_new(BIO_s_mem()); if (responseBio == NULL) { goto end; } BIO_write(responseBio, resultBuffer, resultLength); *tsResponse = d2i_TS_RESP_bio(responseBio, NULL); if (*tsResponse == NULL) { goto end; } result = TNOERR; } else { switch (httpResult) { case HTTP_NOLIVEINTERNET_ERROR: result = TNONET; break; case HTTP_TIMEOUT_ERROR: result = TTIMEOUT; break; case HTTP_RESPONSESTATUS_ERROR: result = TSERVERERROR; break; default: result = TINTERNALERROR; break; } } end: free_url(url); if (tsRequest != NULL) { TS_REQ_free(tsRequest); } if (requestBio != NULL) { BIO_free_all(requestBio); } if (responseBio != NULL) { BIO_free_all(responseBio); } if (request != NULL) { memory_free(request); } if (contentBuffer != NULL) { memory_free(contentBuffer); } if (resultBuffer != NULL) { memory_free(resultBuffer); } if (urlBuffer != NULL) { memory_free(urlBuffer); } return result; }