RTR3DECL(int) RTHttpCertDigest(RTHTTP hHttp, char *pcszCert, size_t cbCert, uint8_t **pabSha1, size_t *pcbSha1, uint8_t **pabSha512, size_t *pcbSha512) { int rc = VINF_SUCCESS; BIO *cert = BIO_new_mem_buf(pcszCert, (int)cbCert); if (cert) { X509 *crt = NULL; if (PEM_read_bio_X509(cert, &crt, NULL, NULL)) { unsigned cb; unsigned char md[EVP_MAX_MD_SIZE]; int rc1 = X509_digest(crt, EVP_sha1(), md, &cb); if (rc1 > 0) { *pabSha1 = (uint8_t*)RTMemAlloc(cb); if (*pabSha1) { memcpy(*pabSha1, md, cb); *pcbSha1 = cb; rc1 = X509_digest(crt, EVP_sha512(), md, &cb); if (rc1 > 0) { *pabSha512 = (uint8_t*)RTMemAlloc(cb); if (*pabSha512) { memcpy(*pabSha512, md, cb); *pcbSha512 = cb; } else rc = VERR_NO_MEMORY; } else rc = VERR_HTTP_CACERT_WRONG_FORMAT; if (RT_FAILURE(rc)) RTMemFree(*pabSha1); } else rc = VERR_NO_MEMORY; } else rc = VERR_HTTP_CACERT_WRONG_FORMAT; X509_free(crt); } else rc = VERR_HTTP_CACERT_WRONG_FORMAT; BIO_free(cert); } else rc = VERR_INTERNAL_ERROR; return rc; }
static int tls_get_peer_cert_hash(struct tls *ctx, char **hash) { unsigned char d[EVP_MAX_MD_SIZE]; char *dhex = NULL; unsigned int dlen; int rv = -1; *hash = NULL; if (ctx->ssl_peer_cert == NULL) return (0); if (X509_digest(ctx->ssl_peer_cert, EVP_sha256(), d, &dlen) != 1) { tls_set_errorx(ctx, "digest failed"); goto err; } if (tls_hex_string(d, dlen, &dhex, NULL) != 0) { tls_set_errorx(ctx, "digest hex string failed"); goto err; } if (asprintf(hash, "SHA256:%s", dhex) == -1) { tls_set_errorx(ctx, "out of memory"); *hash = NULL; goto err; } rv = 0; err: free(dhex); return (rv); }
char * be_tls_get_certificate_hash(Port *port, size_t *len) { #ifdef HAVE_X509_GET_SIGNATURE_NID X509 *server_cert; char *cert_hash; const EVP_MD *algo_type = NULL; unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */ unsigned int hash_size; int algo_nid; *len = 0; server_cert = SSL_get_certificate(port->ssl); if (server_cert == NULL) return NULL; /* * Get the signature algorithm of the certificate to determine the hash * algorithm to use for the result. */ if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert), &algo_nid, NULL)) elog(ERROR, "could not determine server certificate signature algorithm"); /* * The TLS server's certificate bytes need to be hashed with SHA-256 if * its signature algorithm is MD5 or SHA-1 as per RFC 5929 * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else * is used, the same hash as the signature algorithm is used. */ switch (algo_nid) { case NID_md5: case NID_sha1: algo_type = EVP_sha256(); break; default: algo_type = EVP_get_digestbynid(algo_nid); if (algo_type == NULL) elog(ERROR, "could not find digest for NID %s", OBJ_nid2sn(algo_nid)); break; } /* generate and save the certificate hash */ if (!X509_digest(server_cert, algo_type, hash, &hash_size)) elog(ERROR, "could not generate server certificate hash"); cert_hash = palloc(hash_size); memcpy(cert_hash, hash, hash_size); *len = hash_size; return cert_hash; #else ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("channel binding type \"tls-server-end-point\" is not supported by this build"))); return NULL; #endif }
/* * Obtain client's fingerprint. */ char *get_fingerprint_for_client(aClient *cptr) { unsigned int n; unsigned int l; unsigned char md[EVP_MAX_MD_SIZE]; static char hex[EVP_MAX_MD_SIZE * 2 + 1]; char hexchars[16] = "0123456789abcdef"; const EVP_MD *digest = EVP_sha256(); X509 *x509_clientcert = NULL; if (!MyConnect(cptr) || !cptr->local->ssl) return NULL; x509_clientcert = SSL_get_peer_certificate(cptr->local->ssl); if (x509_clientcert) { if (X509_digest(x509_clientcert, digest, md, &n)) { int j = 0; for (l=0; l<n; l++) { hex[j++] = hexchars[(md[l] >> 4) & 0xF]; hex[j++] = hexchars[md[l] & 0xF]; } hex[j] = '\0'; X509_free(x509_clientcert); return hex; } X509_free(x509_clientcert); }
// Generate a string containing a digest. The digest time is 'ssh1' or // 'md5', and the resulting string is of the form "aa:12:5c:' and so on std::string cert_get_digest(const std::string& digest_type, X509 *cert) { unsigned char digest_data[BUFFER_READ_SIZE]; unsigned int len = sizeof(digest_data); std::stringstream result; const EVP_MD* digest = NULL; // we could use EVP_get_digestbyname, but that requires initializer code which // would require us to complicate things by plumbing it into the system. if (digest_type == "md5") { digest = EVP_md5(); } else if (digest_type == "sha1") { digest = EVP_sha1(); } else { return std::string(); } X509_digest(cert, digest, digest_data, &len); result << std::hex << std::setprecision(2); for (unsigned int i=0; i < len; i++) { if (i != 0) { result << ":"; } result << std::setfill('0') << std::setw(2) << (int)digest_data[i]; } return result.str(); }
bool ssl_options_t::has_fingerprint(boost::asio::ssl::verify_context &ctx) const { // can we check the certificate against a list of fingerprints? if (!fingerprints_.empty()) { X509_STORE_CTX *sctx = ctx.native_handle(); if (!sctx) { MERROR("Error getting verify_context handle"); return false; } X509* cert = nullptr; const STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(sctx); if (!chain || sk_X509_num(chain) < 1 || !(cert = sk_X509_value(chain, 0))) { MERROR("No certificate found in verify_context"); return false; } // buffer for the certificate digest and the size of the result std::vector<uint8_t> digest(EVP_MAX_MD_SIZE); unsigned int size{ 0 }; // create the digest from the certificate if (!X509_digest(cert, EVP_sha256(), digest.data(), &size)) { MERROR("Failed to create certificate fingerprint"); return false; } // strip unnecessary bytes from the digest digest.resize(size); return std::binary_search(fingerprints_.begin(), fingerprints_.end(), digest); }
static int ssl_cert_digest(SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str) { X509* p_cert = SSL_get_peer_certificate(p_ssl); unsigned int num_bytes = 0; if (p_cert == NULL) { return 0; } str_reserve(p_str, EVP_MAX_MD_SIZE); str_empty(p_str); str_rpad(p_str, EVP_MAX_MD_SIZE); if (!X509_digest(p_cert, EVP_sha256(), (unsigned char*) str_getbuf(p_str), &num_bytes)) { die("X509_digest failed"); } X509_free(p_cert); if (tunable_debug_ssl) { unsigned int i; str_alloc_text(&debug_str, "Cert digest:"); for (i = 0; i < num_bytes; ++i) { str_append_char(&debug_str, ' '); str_append_ulong( &debug_str, (unsigned long) (unsigned char) str_get_char_at(p_str, i)); } vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } str_trunc(p_str, num_bytes); return 1; }
/** * Updates some data in the ssl connection * @param ssl reference to ssl connection * @return TRUE, if not successful FALSE */ int update_ssl_cert_data(ssl_connection *ssl) { #ifdef HAVE_OPENSSL unsigned char md5[EVP_MAX_MD_SIZE]; ASSERT(ssl); if ((ssl->cert = SSL_get_peer_certificate (ssl->handler)) == NULL) { return FALSE; } /* RATS: ignore */ /* buffer is dynamically allocated */ ssl->cert_issuer=X509_NAME_oneline (X509_get_issuer_name (ssl->cert),0,0); /* RATS: ignore */ /* buffer is dynamically allocated */ ssl->cert_subject=X509_NAME_oneline (X509_get_subject_name (ssl->cert),0,0); X509_digest(ssl->cert,EVP_md5(), md5, &ssl->cert_md5_len); ssl->cert_md5= (unsigned char *) xstrdup((char *) md5); return TRUE; #else return FALSE; #endif }
SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert) { int PrefixLength; BYTE CertificateHash[32]; UINT32 CertificateHashLength; BYTE* ChannelBindingToken; UINT32 ChannelBindingTokenLength; SEC_CHANNEL_BINDINGS* ChannelBindings; SecPkgContext_Bindings* ContextBindings; ZeroMemory(CertificateHash, sizeof(CertificateHash)); X509_digest(cert, EVP_sha256(), CertificateHash, &CertificateHashLength); PrefixLength = strlen(TLS_SERVER_END_POINT); ChannelBindingTokenLength = PrefixLength + CertificateHashLength; ContextBindings = (SecPkgContext_Bindings*) malloc(sizeof(SecPkgContext_Bindings)); ZeroMemory(ContextBindings, sizeof(SecPkgContext_Bindings)); ContextBindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength; ChannelBindings = (SEC_CHANNEL_BINDINGS*) malloc(ContextBindings->BindingsLength); ZeroMemory(ChannelBindings, ContextBindings->BindingsLength); ContextBindings->Bindings = ChannelBindings; ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength; ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS); ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset]; strcpy((char*) ChannelBindingToken, TLS_SERVER_END_POINT); CopyMemory(&ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength); return ContextBindings; }
char *tls_fingerprint(X509 *peercert, const char *dgst) { const char *myname = "tls_fingerprint"; const EVP_MD *md_alg; unsigned char md_buf[EVP_MAX_MD_SIZE]; unsigned int md_len; int i; char *result = 0; /* Previously available in "init" routine. */ if ((md_alg = EVP_get_digestbyname(dgst)) == 0) acl_msg_panic("%s: digest algorithm \"%s\" not found", myname, dgst); /* Fails when serialization to ASN.1 runs out of memory */ if (X509_digest(peercert, md_alg, md_buf, &md_len) == 0) acl_msg_fatal("%s: error computing certificate %s digest (out of memory?)", myname, dgst); /* Check for OpenSSL contract violation */ if (md_len > EVP_MAX_MD_SIZE || (int) md_len >= INT_MAX / 3) acl_msg_panic("%s: unexpectedly large %s digest size: %u", myname, dgst, md_len); result = acl_mymalloc(md_len * 3); for (i = 0; i < (int) md_len; i++) { result[i * 3] = hexcodes[(md_buf[i] & 0xf0) >> 4U]; result[(i * 3) + 1] = hexcodes[(md_buf[i] & 0x0f)]; result[(i * 3) + 2] = (i + 1 != (int) md_len) ? ':' : '\0'; } return (result); }
static int loadCertFile(SSL_CTX *pCtx, const char *pFile, int type) { char *pBegin, buf[MAX_CERT_LENGTH]; BIO *in; X509 *cert = NULL; int len; int ret; unsigned int digestlen; unsigned char digest[EVP_MAX_MD_SIZE]; /* THIS FILE TYPE WILL NOT BE HANDLED HERE. * Just left this here in case of future implementation.*/ if (translateType(type) == SSL_FILETYPE_ASN1) return LS_FAIL; len = loadPemWithMissingDash(pFile, buf, MAX_CERT_LENGTH, &pBegin); if (len == -1) return LS_FAIL; in = BIO_new_mem_buf((void *)pBegin, len); cert = PEM_read_bio_X509(in, NULL, 0, NULL); BIO_free(in); if (!cert) return LS_FAIL; if (( ret = SSL_CTX_use_certificate(pCtx, cert)) == 1 ) { if ( X509_digest(cert, EVP_sha1(), digest, &digestlen) == 0) LS_DBG_L("Creating cert digest failed"); else if (SslContext::setupIdContext(pCtx, digest, digestlen) != LS_OK) LS_DBG_L("Digest id context failed"); } X509_free(cert); return ret; }
/** * Compute the fingerprint. */ static int meth_digest(lua_State* L) { unsigned int bytes; const EVP_MD *digest = NULL; unsigned char buffer[EVP_MAX_MD_SIZE]; char hex_buffer[EVP_MAX_MD_SIZE*2]; X509 *cert = lsec_checkx509(L, 1); const char *str = luaL_optstring(L, 2, NULL); if (!str) digest = EVP_sha1(); else { if (!strcmp(str, "sha1")) digest = EVP_sha1(); else if (!strcmp(str, "sha256")) digest = EVP_sha256(); else if (!strcmp(str, "sha512")) digest = EVP_sha512(); } if (!digest) { lua_pushnil(L); lua_pushstring(L, "digest algorithm not supported"); return 2; } if (!X509_digest(cert, digest, buffer, &bytes)) { lua_pushnil(L); lua_pushstring(L, "error processing the certificate"); return 2; } to_hex((char*)buffer, bytes, hex_buffer); lua_pushlstring(L, hex_buffer, bytes*2); return 1; }
int rb_ssl_get_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN]) { X509 *cert; long res; if (F->ssl == NULL) return 0; cert = SSL_get_peer_certificate((SSL *) F->ssl); if(cert != NULL) { res = SSL_get_verify_result((SSL *) F->ssl); if( res == X509_V_OK || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE || res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || res == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) { unsigned int certfp_length = RB_SSL_CERTFP_LEN; X509_digest(cert, EVP_sha256(), certfp, &certfp_length); X509_free(cert); return 1; } X509_free(cert); } return 0; }
// Verify the signed block, the first 32 bytes of the data must be the certificate hash to work. int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert, char** data) { unsigned int size, r; BIO *out = NULL; PKCS7 *message = NULL; char* data2 = NULL; char hash[UTIL_HASHSIZE]; STACK_OF(X509) *st = NULL; cert->x509 = NULL; cert->pkey = NULL; *data = NULL; message = d2i_PKCS7(NULL, (const unsigned char**)&signature, signlen); if (message == NULL) goto error; out = BIO_new(BIO_s_mem()); // Lets rebuild the original message and check the size size = i2d_PKCS7(message, NULL); if (size < (unsigned int)signlen) goto error; // Check the PKCS7 signature, but not the certificate chain. r = PKCS7_verify(message, NULL, NULL, NULL, out, PKCS7_NOVERIFY); if (r == 0) goto error; // If data block contains less than 32 bytes, fail. size = BIO_get_mem_data(out, &data2); if (size <= UTIL_HASHSIZE) goto error; // Copy the data block *data = (char*)malloc(size + 1); if (*data == NULL) goto error; memcpy(*data, data2, size); (*data)[size] = 0; // Get the certificate signer st = PKCS7_get0_signers(message, NULL, PKCS7_NOVERIFY); cert->x509 = X509_dup(sk_X509_value(st, 0)); sk_X509_free(st); // Get a full certificate hash of the signer r = UTIL_HASHSIZE; X509_digest(cert->x509, EVP_sha256(), (unsigned char*)hash, &r); // Check certificate hash with first 32 bytes of data. if (memcmp(hash, *data, UTIL_HASHSIZE) != 0) goto error; // Approved, cleanup and return. BIO_free(out); PKCS7_free(message); return size; error: if (out != NULL) BIO_free(out); if (message != NULL) PKCS7_free(message); if (*data != NULL) free(*data); if (cert->x509 != NULL) { X509_free(cert->x509); cert->x509 = NULL; } return 0; }
char * get_fingerprint(SSL *ssl_h) { char *string = NULL; unsigned char fp_digest[EVP_MAX_MD_SIZE]; X509 *x509_data = SSL_get_peer_certificate(ssl_h); if (x509_data) { unsigned int fp_digest_size = sizeof(fp_digest); memset(fp_digest, 0x00, sizeof(fp_digest)); if (X509_digest(x509_data, EVP_md5(), fp_digest, &fp_digest_size)) { string = (char *)malloc(MD5_DIGEST_LENGTH * 3 + 1); if (string) { int loop, pos =0; for(loop=0; loop<MD5_DIGEST_LENGTH; loop++) { if (loop) pos += sprintf(&string[pos], ":%02x", fp_digest[loop]); else pos = sprintf(&string[pos], "%02x", fp_digest[loop]); } } } X509_free(x509_data); } return string; }
struct dtls_context * create_dtls_context(const char *common) { if (common == NULL) return NULL; struct dtls_context *context = (struct dtls_context *)calloc(1, sizeof *context); if (context == NULL) return NULL; SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_CTX *ctx = SSL_CTX_new(DTLSv1_method()); if (ctx == NULL) goto ctx_err; context->ctx = ctx; // ALL:NULL:eNULL:aNULL if (SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1) goto ctx_err; SSL_CTX_set_read_ahead(ctx, 1); // for DTLS SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_peer_certificate_cb); EVP_PKEY *key = gen_key(); if (key == NULL) goto ctx_err; SSL_CTX_use_PrivateKey(ctx, key); X509 *cert = gen_cert(key, common, 365); if (cert == NULL) goto ctx_err; SSL_CTX_use_certificate(ctx, cert); if (SSL_CTX_check_private_key(ctx) != 1) goto ctx_err; unsigned int len; unsigned char buf[BUFFER_SIZE]; X509_digest(cert, EVP_sha256(), buf, &len); char *p = context->fingerprint; for (int i = 0; i < len; ++i) { snprintf(p, 4, "%02X:", buf[i]); p += 3; } *(p - 1) = 0; if (0) { ctx_err: SSL_CTX_free(ctx); free(context); context = NULL; } return context; }
static unsigned int ma_get_cert_fingerprint(X509 *cert, EVP_MD *digest, unsigned char *fingerprint, unsigned int *fp_length) { if (*fp_length < EVP_MD_size(digest)) return 0; if (!X509_digest(cert, digest, fingerprint, fp_length)) return 0; return *fp_length; }
/* * Check if the SSL/TLS certificate exists in the certificates file. */ int check_cert(X509 *pcert, unsigned char *pmd, unsigned int *pmdlen) { int n, r; FILE *fd; char b; char *certf; X509 *cert; unsigned char md[EVP_MAX_MD_SIZE]; unsigned int mdlen; r = 0; cert = NULL; n = snprintf(&b, 1, "%s/%s", env.home, PATHNAME_CERTS); if (env.pathmax != -1 && n > env.pathmax) fatal(ERROR_PATHNAME, "pathname limit %ld exceeded: %d\n", env.pathmax, n); certf = (char *)xmalloc((n + 1) * sizeof(char)); snprintf(certf, n + 1, "%s/%s", env.home, PATHNAME_CERTS); if (!exists_file(certf)) { xfree(certf); return 0; } fd = fopen(certf, "r"); xfree(certf); if (fd == NULL) return -1; while ((cert = PEM_read_X509(fd, &cert, NULL, NULL)) != NULL) { if (X509_subject_name_cmp(cert, pcert) != 0 || X509_issuer_name_cmp(cert, pcert) != 0) continue; if (!X509_digest(cert, EVP_md5(), md, &mdlen) || *pmdlen != mdlen) continue; if (memcmp(pmd, md, mdlen) != 0) { r = -1; break; } r = 1; break; } fclose(fd); X509_free(cert); return r; }
vector<uint8_t> X509_digest(::X509* x509, const ::EVP_MD* md) { unsigned int n; unsigned char buf[EVP_MAX_MD_SIZE]; if (!X509_digest(x509, md, buf, &n)) { return vector<uint8_t>(); // Throw instead? } return vector<uint8_t>(buf, buf+n); }
__declspec(dllexport) void ILibWrapper_InitializeDTLS() { ctx = SSL_CTX_new(DTLSv1_method()); SSL_CTX_use_certificate(ctx, selftlscert.x509); SSL_CTX_use_PrivateKey(ctx,selftlscert.pkey); int l = 32; X509_digest(selftlscert.x509, EVP_get_digestbyname("sha256"), (unsigned char*)tlsServerCertThumbprint, (unsigned int*)&l); }
int dtls_get_cert_fingerprint(const char *certPath, DTLS_FINGERPRINT_T *pFingerprint) { int rc = 0; unsigned int lenHash; X509 *pX509 = NULL; BIO *pBIO = NULL; const EVP_MD *pEvp = NULL; if(!certPath || !pFingerprint) { return -1; } pFingerprint->buf[0] = '\0'; pFingerprint->len = 0; if(!(pEvp = dtlsFingerprintTypeToEVP(pFingerprint->type))) { LOG(X_ERROR("DTLS invalid fingerprint digest type")); return -1; } if(!(pBIO = BIO_new(BIO_s_file()))) { LOG(X_ERROR("DTLS BIO_new failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); return -1; } if(rc >= 0 && BIO_read_filename(pBIO, certPath) != 1){ LOG(X_ERROR("DTLS BIO_read_filename failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); rc = -1; } if(rc >= 0 && !(pX509 = PEM_read_bio_X509(pBIO, NULL, 0, NULL))){ LOG(X_ERROR("DTLS PEM_read_bio_X509 failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); rc = -1; } lenHash = sizeof(pFingerprint->buf); if(rc >= 0 && (X509_digest(pX509, pEvp, pFingerprint->buf, &lenHash) != 1 || lenHash <= 0)) { LOG(X_ERROR("DTLS X509_digest failed for '%s': %s"), certPath, ERR_reason_error_string(ERR_get_error())); rc = -1; } else { pFingerprint->len = lenHash; rc = pFingerprint->len; } //avc_dumpHex(stderr, buf, sizeof(buf), 1); if(pX509) { X509_free(pX509); } if(pBIO) { BIO_free_all(pBIO); } return rc; }
std::string genSHA1ForCertificate(X509* cert) { const EVP_MD* fprint_type = EVP_sha1(); unsigned char fprint[EVP_MAX_MD_SIZE] = {0}; unsigned int fprint_size = 0; if (X509_digest(cert, fprint_type, fprint, &fprint_size)) { return genKIDProperty(fprint, fprint_size); } return ""; }
void DtlsTransport::GenerateFingerprints() { MS_TRACE(); for (auto it = DtlsTransport::string2FingerprintAlgorithm.begin(); it != DtlsTransport::string2FingerprintAlgorithm.end(); ++it) { std::string algorithm_str = it->first; FingerprintAlgorithm algorithm = it->second; uint8_t binary_fingerprint[EVP_MAX_MD_SIZE]; unsigned int size = 0; char hex_fingerprint[(EVP_MAX_MD_SIZE * 2) + 1]; const EVP_MD* hash_function; int ret; switch (algorithm) { case FingerprintAlgorithm::SHA1: hash_function = EVP_sha1(); break; case FingerprintAlgorithm::SHA224: hash_function = EVP_sha224(); break; case FingerprintAlgorithm::SHA256: hash_function = EVP_sha256(); break; case FingerprintAlgorithm::SHA384: hash_function = EVP_sha384(); break; case FingerprintAlgorithm::SHA512: hash_function = EVP_sha512(); break; default: MS_ABORT("unknown algorithm"); } ret = X509_digest(DtlsTransport::certificate, hash_function, binary_fingerprint, &size); if (ret == 0) { MS_ERROR("X509_digest() failed"); MS_THROW_ERROR("Fingerprints generation failed"); } // Convert to hexadecimal format in lowecase without colons. for (unsigned int i = 0; i < size; i++) { std::sprintf(hex_fingerprint + (i * 2), "%.2x", binary_fingerprint[i]); } hex_fingerprint[size * 2] = '\0'; MS_DEBUG("%-7s fingerprint: %s", algorithm_str.c_str(), hex_fingerprint); // Store in the JSON. DtlsTransport::localFingerprints[algorithm_str] = hex_fingerprint; } }
/* Show the user all relevant information about a certificate: subject, * issuer, validity dates and fingerprints. */ static void ssl_showcert(X509 *cert, int loglev) { char *buf, *from, *to; X509_NAME *name; unsigned int len; unsigned char md[EVP_MAX_MD_SIZE]; /* Subject and issuer names */ if ((name = X509_get_subject_name(cert))) { buf = ssl_printname(name); putlog(loglev, "*", "TLS: certificate subject: %s", buf); nfree(buf); } else putlog(loglev, "*", "TLS: cannot get subject name from certificate!"); if ((name = X509_get_issuer_name(cert))) { buf = ssl_printname(name); putlog(loglev, "*", "TLS: certificate issuer: %s", buf); nfree(buf); } else putlog(loglev, "*", "TLS: cannot get issuer name from certificate!"); /* Fingerprints */ X509_digest(cert, EVP_md5(), md, &len); /* MD5 hash */ if (len <= sizeof(md)) { buf = hex_to_string(md, len); putlog(loglev, "*", "TLS: certificate MD5 Fingerprint: %s", buf); OPENSSL_free(buf); } X509_digest(cert, EVP_sha1(), md, &len); /* SHA-1 hash */ if (len <= sizeof(md)) { buf = hex_to_string(md, len); putlog(loglev, "*", "TLS: certificate SHA1 Fingerprint: %s", buf); OPENSSL_free(buf); } /* Validity time */ from = ssl_printtime(X509_get_notBefore(cert)); to = ssl_printtime(X509_get_notAfter(cert)); putlog(loglev, "*", "TLS: certificate valid from %s to %s", from, to); nfree(from); nfree(to); }
std::string X509_digest(::X509* x509, const ::EVP_MD* md) { unsigned int n; unsigned char buf[EVP_MAX_MD_SIZE]; if (!X509_digest(x509, md, buf, &n)) { return Util::emptyString; // Throw instead? } std::string ret(n * 2, '\0'); for(unsigned int i = 0; i < n; ++i) { sprintf(&ret[i*2], "%02x", (unsigned int)buf[i]); } return ret; }
void VerifyCertificate() { X509* cert; ssl_cert* certinfo = new ssl_cert; this->certificate = certinfo; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; cert = SSL_get_peer_certificate(sess); if (!cert) { certinfo->error = "Could not get peer certificate: "+std::string(get_error()); return; } certinfo->invalid = (SSL_get_verify_result(sess) != X509_V_OK); if (!SelfSigned) { certinfo->unknownsigner = false; certinfo->trusted = true; } else { certinfo->unknownsigner = true; certinfo->trusted = false; } char buf[512]; X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); certinfo->dn = buf; X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); certinfo->issuer = buf; if (!X509_digest(cert, profile->GetDigest(), md, &n)) { certinfo->error = "Out of memory generating fingerprint"; } else { certinfo->fingerprint = BinToHex(md, n); } if ((ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(cert), ServerInstance->Time()) == -1) || (ASN1_UTCTIME_cmp_time_t(X509_get_notBefore(cert), ServerInstance->Time()) == 0)) { certinfo->error = "Not activated, or expired certificate"; } X509_free(cert); }
PKI_DIGEST *PKI_X509_CERT_fingerprint(const PKI_X509_CERT *x, const PKI_DIGEST_ALG *alg ){ PKI_DIGEST *ret = NULL; PKI_X509_CERT_VALUE *cert = NULL; unsigned char buf[EVP_MAX_MD_SIZE]; unsigned int ret_size = 0; /* Check that we have a valid certificate */ if( !x || !x->value || x->type != PKI_DATATYPE_X509_CERT ) return ( NULL ); cert = (PKI_X509_CERT_VALUE *) x->value; /* If no Algorithm is provided, we use the default one */ if( alg == NULL ) { alg = PKI_DIGEST_ALG_DEFAULT; } /* Calculate the Digest */ if (!X509_digest(cert,alg,buf,&ret_size)) { /* ERROR */ return ( NULL ); } /* Allocate the return structure */ if((ret = PKI_Malloc ( sizeof( PKI_DIGEST) )) == NULL ) { /* Memory Allocation Error! */ return( NULL ); } /* Allocate the buffer */ if((ret->digest = PKI_Malloc ( ret_size )) == NULL ) { /* Memory Error */ PKI_Free ( ret ); return( NULL ); } /* Set the size of the Digest */ ret->size = ret_size; /* Copy the Digest Data */ memcpy( ret->digest, buf, ret->size ); /* Sets the algorithm used */ ret->algor = alg; return ( ret ); }
int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method) { X509 *cert; int res; if (F->ssl == NULL) return 0; cert = SSL_get_peer_certificate((SSL *) F->ssl); if(cert != NULL) { res = SSL_get_verify_result((SSL *) F->ssl); if( res == X509_V_OK || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE || res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || res == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) { const EVP_MD *evp; unsigned int len; switch(method) { case RB_SSL_CERTFP_METH_SHA1: evp = EVP_sha1(); len = RB_SSL_CERTFP_LEN_SHA1; break; case RB_SSL_CERTFP_METH_SHA256: evp = EVP_sha256(); len = RB_SSL_CERTFP_LEN_SHA256; break; case RB_SSL_CERTFP_METH_SHA512: evp = EVP_sha512(); len = RB_SSL_CERTFP_LEN_SHA512; break; default: return 0; } X509_digest(cert, evp, certfp, &len); X509_free(cert); return len; } X509_free(cert); } return 0; }
/* * Get SSL/TLS certificate check it, maybe ask user about it and act * accordingly. */ int get_cert(session *ssn) { X509 *cert; unsigned char md[EVP_MAX_MD_SIZE]; unsigned int mdlen; long verify; mdlen = 0; if (!(cert = SSL_get_peer_certificate(ssn->sslconn))) return -1; verify = SSL_get_verify_result(ssn->sslconn); if (!((verify == X509_V_OK) || (verify == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) || (verify == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY))) { error("certificate verification failed; %d\n", verify); goto fail; } if (verify != X509_V_OK) { if (!(X509_digest(cert, EVP_md5(), md, &mdlen))) return -1; switch (check_cert(cert, md, &mdlen)) { case 0: if (isatty(STDIN_FILENO) == 0) fatal(ERROR_CERTIFICATE, "%s\n", "can't accept certificate in " "non-interactive mode"); print_cert(cert, md, &mdlen); if (store_cert(cert) == -1) goto fail; break; case -1: error("certificate mismatch occured\n"); goto fail; } } X509_free(cert); return 0; fail: X509_free(cert); return -1; }
static int handle_certificate(const char *filename, const char *fullpath) { STACK_OF(X509_INFO) *inf; X509_INFO *x; BIO *b; const char *ext; unsigned char digest[EVP_MAX_MD_SIZE]; X509_NAME *name = NULL; int i, type, ret = -1; ext = strrchr(filename, '.'); if (ext == NULL) return 0; for (i = 0; i < countof(file_extensions); i++) { if (strcasecmp(file_extensions[i], ext+1) == 0) break; } if (i >= countof(file_extensions)) return -1; b = BIO_new_file(fullpath, "r"); if (!b) return -1; inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); BIO_free(b); if (!inf) return -1; if (sk_X509_INFO_num(inf) == 1) { x = sk_X509_INFO_value(inf, 0); if (x->x509) { type = TYPE_CERT; name = X509_get_subject_name(x->x509); X509_digest(x->x509, evpmd, digest, NULL); } else if (x->crl) { type = TYPE_CRL; name = X509_CRL_get_issuer(x->crl); X509_CRL_digest(x->crl, evpmd, digest, NULL); } if (name && do_hash_new) add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0); if (name && do_hash_old) add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0); } else { fprintf(stderr, "WARNING: %s does not contain exactly one certificate or CRL: skipping\n", filename); } sk_X509_INFO_pop_free(inf, X509_INFO_free); return ret; }