int ca_validate_cert(struct iked *env, struct iked_static_id *id, void *data, size_t len) { struct ca_store *store = env->sc_priv; X509_STORE_CTX csc; BIO *rawcert = NULL; X509 *cert = NULL; int ret = -1, result, error; size_t idlen, idoff; const u_int8_t *idptr; X509_NAME *idname = NULL, *subject; const char *errstr = "failed"; if (len == 0) { /* Data is already an X509 certificate */ cert = (X509 *)data; } else { /* Convert data to X509 certificate */ if ((rawcert = BIO_new_mem_buf(data, len)) == NULL) goto done; if ((cert = d2i_X509_bio(rawcert, NULL)) == NULL) goto done; } /* Certificate needs a valid subjectName */ if ((subject = X509_get_subject_name(cert)) == NULL) { errstr = "invalid subject"; goto done; } if (id != NULL) { if ((ret = ca_validate_pubkey(env, id, X509_get_pubkey(cert), 0)) == 0) { errstr = "public key found, ok"; goto done; } switch (id->id_type) { case IKEV2_ID_ASN1_DN: idoff = id->id_offset; if (id->id_length <= idoff) { errstr = "invalid ASN1_DN id length"; goto done; } idlen = id->id_length - idoff; idptr = id->id_data + idoff; if ((idname = d2i_X509_NAME(NULL, &idptr, idlen)) == NULL || X509_NAME_cmp(subject, idname) != 0) { errstr = "ASN1_DN identifier mismatch"; goto done; } break; default: if (ca_x509_subjectaltname_cmp(cert, id) != 0) { errstr = "invalid subjectAltName extension"; goto done; } break; } } bzero(&csc, sizeof(csc)); X509_STORE_CTX_init(&csc, store->ca_cas, cert, NULL); if (store->ca_cas->param->flags & X509_V_FLAG_CRL_CHECK) { X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK); X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL); } result = X509_verify_cert(&csc); error = csc.error; X509_STORE_CTX_cleanup(&csc); if (error != 0) { errstr = X509_verify_cert_error_string(error); goto done; } if (!result) { /* XXX should we accept self-signed certificates? */ errstr = "rejecting self-signed certificate"; goto done; } /* Success */ ret = 0; done: if (cert != NULL) log_debug("%s: %s %.100s", __func__, cert->name, ret == 0 ? "ok" : errstr); if (idname != NULL) X509_NAME_free(idname); if (rawcert != NULL) { BIO_free(rawcert); if (cert != NULL) X509_free(cert); } return (ret); }
/* based on BSD-style licensed code of mod_ssl */ static int crl_check(CLI *c, X509_STORE_CTX *callback_ctx) { X509_STORE_CTX store_ctx; X509_OBJECT obj; X509_NAME *subject; X509_NAME *issuer; X509 *cert; X509_CRL *crl; X509_REVOKED *revoked; EVP_PKEY *pubkey; long serial; int i, n, rc; char *cp; ASN1_TIME *last_update=NULL, *next_update=NULL; /* determine certificate ingredients in advance */ cert=X509_STORE_CTX_get_current_cert(callback_ctx); subject=X509_get_subject_name(cert); issuer=X509_get_issuer_name(cert); /* try to retrieve a CRL corresponding to the _subject_ of * the current certificate in order to verify it's integrity */ memset((char *)&obj, 0, sizeof obj); X509_STORE_CTX_init(&store_ctx, c->opt->revocation_store, NULL, NULL); rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj); X509_STORE_CTX_cleanup(&store_ctx); crl=obj.data.crl; if(rc>0 && crl) { cp=X509_NAME_oneline(subject, NULL, 0); s_log(LOG_INFO, "CRL: issuer: %s", cp); OPENSSL_free(cp); last_update=X509_CRL_get_lastUpdate(crl); next_update=X509_CRL_get_nextUpdate(crl); log_time(LOG_INFO, "CRL: last update", last_update); log_time(LOG_INFO, "CRL: next update", next_update); /* verify the signature on this CRL */ pubkey=X509_get_pubkey(cert); if(X509_CRL_verify(crl, pubkey)<=0) { s_log(LOG_WARNING, "CRL: Invalid signature"); X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); X509_OBJECT_free_contents(&obj); if(pubkey) EVP_PKEY_free(pubkey); return 0; /* reject connection */ } if(pubkey) EVP_PKEY_free(pubkey); /* check date of CRL to make sure it's not expired */ if(!next_update) { s_log(LOG_WARNING, "CRL: Invalid nextUpdate field"); X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); X509_OBJECT_free_contents(&obj); return 0; /* reject connection */ } if(X509_cmp_current_time(next_update)<0) { s_log(LOG_WARNING, "CRL: CRL Expired - revoking all certificates"); X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CRL_HAS_EXPIRED); X509_OBJECT_free_contents(&obj); return 0; /* reject connection */ } X509_OBJECT_free_contents(&obj); } /* try to retrieve a CRL corresponding to the _issuer_ of * the current certificate in order to check for revocation */ memset((char *)&obj, 0, sizeof obj); X509_STORE_CTX_init(&store_ctx, c->opt->revocation_store, NULL, NULL); rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj); X509_STORE_CTX_cleanup(&store_ctx); crl=obj.data.crl; if(rc>0 && crl) { /* check if the current certificate is revoked by this CRL */ n=sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); for(i=0; i<n; i++) { revoked=sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); if(ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(cert)) == 0) { serial=ASN1_INTEGER_get(revoked->serialNumber); cp=X509_NAME_oneline(issuer, NULL, 0); s_log(LOG_WARNING, "CRL: Certificate with serial %ld (0x%lX) " "revoked per CRL from issuer %s", serial, serial, cp); OPENSSL_free(cp); X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CERT_REVOKED); X509_OBJECT_free_contents(&obj); return 0; /* reject connection */ } } X509_OBJECT_free_contents(&obj); } return 1; /* accept connection */ }
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; int n,i; unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; BUF_MEM *buf; X509_STORE_CTX xs_ctx; X509_OBJECT obj; /* TLSv1 sends a chain with nothing in it, instead of an alert */ buf=s->init_buf; if (!BUF_MEM_grow_clean(buf,10)) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } if (x != NULL) { if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL)) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); return(0); } for (;;) { n=i2d_X509(x,NULL); if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } p=(unsigned char *)&(buf->data[l]); l2n3(n,p); i2d_X509(x,&p); l+=n+3; if (X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)) == 0) break; i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509, X509_get_issuer_name(x),&obj); if (i <= 0) break; x=obj.data.x509; /* Count is one too high since the X509_STORE_get uped the * ref count */ X509_free(x); } X509_STORE_CTX_cleanup(&xs_ctx); } /* Thawte special :-) */ if (s->ctx->extra_certs != NULL) for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); n=i2d_X509(x,NULL); if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) { SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } p=(unsigned char *)&(buf->data[l]); l2n3(n,p); i2d_X509(x,&p); l+=n+3; } l-= (3 + DTLS1_HM_HEADER_LENGTH); p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); l2n3(l,p); l+=3; p=(unsigned char *)&(buf->data[0]); p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l); l+=DTLS1_HM_HEADER_LENGTH; return(l); }
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create, int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno) { int ret=0; ASN1_INTEGER *bs=NULL; X509_STORE_CTX xsc; EVP_PKEY *upkey; upkey = X509_get_pubkey(xca); EVP_PKEY_copy_parameters(upkey,pkey); EVP_PKEY_free(upkey); if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL)) { BIO_printf(bio_err,"Error initialising X509 store\n"); goto end; } if (sno) bs = sno; else if (!(bs = x509_load_serial(CAfile, serialfile, create))) goto end; /* if (!X509_STORE_add_cert(ctx,x)) goto end;*/ /* NOTE: this certificate can/should be self signed, unless it was * a certificate request in which case it is not. */ X509_STORE_CTX_set_cert(&xsc,x); X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); if (!reqfile && X509_verify_cert(&xsc) <= 0) goto end; if (!X509_check_private_key(xca,pkey)) { BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); goto end; } if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end; if (!X509_set_serialNumber(x,bs)) goto end; if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL) goto end; /* hardwired expired */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto end; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx2; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); X509V3_set_nconf(&ctx2, conf); if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end; } if (!X509_sign(x,pkey,digest)) goto end; ret=1; end: X509_STORE_CTX_cleanup(&xsc); if (!ret) ERR_print_errors(bio_err); if (!sno) ASN1_INTEGER_free(bs); return ret; }
unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; int i; unsigned long l=7; BUF_MEM *buf; int no_chain; if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs) no_chain = 1; else no_chain = 0; /* TLSv1 sends a chain with nothing in it, instead of an alert */ buf=s->init_buf; if (!BUF_MEM_grow_clean(buf,10)) { SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); return(0); } if (x != NULL) { if (no_chain) { if (ssl3_add_cert_to_buf(buf, &l, x)) return(0); } else { X509_STORE_CTX xs_ctx; if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) { SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); return(0); } X509_verify_cert(&xs_ctx); /* Don't leave errors in the queue */ ERR_clear_error(); for (i=0; i < sk_X509_num(xs_ctx.chain); i++) { x = sk_X509_value(xs_ctx.chain, i); if (ssl3_add_cert_to_buf(buf, &l, x)) { X509_STORE_CTX_cleanup(&xs_ctx); return 0; } } X509_STORE_CTX_cleanup(&xs_ctx); } } /* Thawte special :-) */ for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); if (ssl3_add_cert_to_buf(buf, &l, x)) return(0); } l-=7; p=(unsigned char *)&(buf->data[4]); l2n3(l,p); l+=3; p=(unsigned char *)&(buf->data[0]); *(p++)=SSL3_MT_CERTIFICATE; l2n3(l,p); l+=4; return(l); }
static int pk7_verify(X509_STORE *cert_store, PKCS7 *p7, BIO *detached, char *ebuf, int ebufsize) { PKCS7_SIGNER_INFO *si; verify_context vctx; BIO *p7bio=NULL; char readbuf[1024*4]; int res = 1; int i; STACK_OF(PKCS7_SIGNER_INFO) *sk; vctx.err = X509_V_OK; ebuf[0] = 0; OpenSSL_add_all_algorithms(); EVP_add_digest(EVP_md5()); EVP_add_digest(EVP_sha1()); ERR_load_crypto_strings(); ERR_clear_error(); X509_VERIFY_PARAM_set_flags(cert_store->param, X509_V_FLAG_CB_ISSUER_CHECK); X509_STORE_set_verify_cb_func(cert_store, verify_callback); p7bio = PKCS7_dataInit(p7, detached); /* We now have to 'read' from p7bio to calculate digests etc. */ while (BIO_read(p7bio, readbuf, sizeof(readbuf)) > 0) ; /* We can now verify signatures */ sk = PKCS7_get_signer_info(p7); if (sk == NULL) { /* there are no signatures on this data */ res = 0; fz_strlcpy(ebuf, "No signatures", ebufsize); goto exit; } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sk); i++) { int rc; si = sk_PKCS7_SIGNER_INFO_value(sk, i); rc = PKCS7_dataVerify(cert_store, &vctx.x509_ctx, p7bio,p7, si); if (rc <= 0 || vctx.err != X509_V_OK) { char tbuf[120]; if (rc <= 0) { fz_strlcpy(ebuf, ERR_error_string(ERR_get_error(), tbuf), ebufsize); } else { /* Error while checking the certificate chain */ snprintf(ebuf, ebufsize, "%s(%d): %s", X509_verify_cert_error_string(vctx.err), vctx.err, vctx.certdesc); } res = 0; goto exit; } } exit: X509_STORE_CTX_cleanup(&vctx.x509_ctx); ERR_free_strings(); return res; }
int MAIN(int argc, char **argv) { unsigned long nmflag = 0; X509_CRL *x=NULL; char *CAfile = NULL, *CApath = NULL; int ret=1,i,num,badops=0; BIO *out=NULL; int informat,outformat; char *infile=NULL,*outfile=NULL; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int fingerprint = 0, crlnumber = 0; const char **pp; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; int do_ver = 0; const EVP_MD *md_alg,*digest=EVP_sha1(); apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,OPENSSL_TYPE__FILE_STDERR,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; if (bio_out == NULL) if ((bio_out=BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); bio_out = BIO_push(tmpbio, bio_out); } #endif } informat=FORMAT_PEM; outformat=FORMAT_PEM; argc--; argv++; num=0; while (argc >= 1) { #ifdef undef if (TINYCLR_SSL_STRCMP(*argv,"-p") == 0) { if (--argc < 1) goto bad; if (!args_from_file(++argv,Nargc,Nargv)) { goto end; }*/ } #endif if (TINYCLR_SSL_STRCMP(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (TINYCLR_SSL_STRCMP(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (TINYCLR_SSL_STRCMP(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (TINYCLR_SSL_STRCMP(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (TINYCLR_SSL_STRCMP(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); do_ver = 1; } else if (TINYCLR_SSL_STRCMP(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); do_ver = 1; } else if (TINYCLR_SSL_STRCMP(*argv,"-verify") == 0) do_ver = 1; else if (TINYCLR_SSL_STRCMP(*argv,"-text") == 0) text = 1; else if (TINYCLR_SSL_STRCMP(*argv,"-hash") == 0) hash= ++num; else if (TINYCLR_SSL_STRCMP(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } else if (TINYCLR_SSL_STRCMP(*argv,"-issuer") == 0) issuer= ++num; else if (TINYCLR_SSL_STRCMP(*argv,"-lastupdate") == 0) lastupdate= ++num; else if (TINYCLR_SSL_STRCMP(*argv,"-nextupdate") == 0) nextupdate= ++num; else if (TINYCLR_SSL_STRCMP(*argv,"-noout") == 0) noout= ++num; else if (TINYCLR_SSL_STRCMP(*argv,"-fingerprint") == 0) fingerprint= ++num; else if (TINYCLR_SSL_STRCMP(*argv,"-crlnumber") == 0) crlnumber= ++num; else if ((md_alg=EVP_get_digestbyname(*argv + 1))) { /* ok */ digest=md_alg; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=crl_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); goto end; } ERR_load_crypto_strings(); x=load_crl(infile,informat); if (x == NULL) { goto end; } if(do_ver) { store = X509_STORE_new(); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); ERR_clear_error(); if(!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if(i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if(!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if(i < 0) goto end; if(i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (num) { for (i=1; i<=num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = (ASN1_INTEGER*)X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out,"crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out,"\n"); } if (hash == i) { BIO_printf(bio_out,"%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } if (lastupdate == i) { BIO_printf(bio_out,"lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out,"\n"); } if (nextupdate == i) { BIO_printf(bio_out,"nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out,"NONE"); BIO_printf(bio_out,"\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x,digest,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(bio_out,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j=0; j<(int)n; j++) { BIO_printf(bio_out,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } } } } out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { TINYCLR_SSL_PERROR(outfile); goto end; } } if (text) X509_CRL_print(out, x); if (noout) { ret = 0; goto end; } if (outformat == FORMAT_ASN1) i=(int)i2d_X509_CRL_bio(out,x); else if (outformat == FORMAT_PEM) i=PEM_write_bio_X509_CRL(out,x); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; } ret=0; end: BIO_free_all(out); BIO_free_all(bio_out); bio_out=NULL; X509_CRL_free(x); if(store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } apps_shutdown(); OPENSSL_EXIT(ret); }
int crl_main(int argc, char **argv) { unsigned long nmflag = 0; X509_CRL *x = NULL; int ret = 1, i; BIO *out = NULL; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; const EVP_MD *digest; char *digest_name = NULL; if (bio_out == NULL) { if ((bio_out = BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); } } digest = EVP_sha1(); memset(&crl_config, 0, sizeof(crl_config)); crl_config.informat = FORMAT_PEM; crl_config.outformat = FORMAT_PEM; if (options_parse(argc, argv, crl_options, &digest_name, NULL) != 0) { crl_usage(); goto end; } if (crl_config.cafile != NULL || crl_config.capath != NULL) crl_config.verify = 1; if (crl_config.nameopt != NULL) { if (set_name_ex(&nmflag, crl_config.nameopt) != 1) { fprintf(stderr, "Invalid -nameopt argument '%s'\n", crl_config.nameopt); goto end; } } if (digest_name != NULL) { if ((digest = EVP_get_digestbyname(digest_name)) == NULL) { fprintf(stderr, "Unknown message digest algorithm '%s'\n", digest_name); goto end; } } x = load_crl(crl_config.infile, crl_config.informat); if (x == NULL) goto end; if (crl_config.verify) { store = X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup, crl_config.cafile, X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup, crl_config.capath, X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if (i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } /* Print requested information the order that the flags were given. */ for (i = 1; i <= argc; i++) { if (crl_config.issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crl_config.crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (crl_config.hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (crl_config.hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (crl_config.lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (crl_config.nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (crl_config.fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int) n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } out = BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (crl_config.outfile == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); } else { if (BIO_write_filename(out, crl_config.outfile) <= 0) { perror(crl_config.outfile); goto end; } } if (crl_config.text) X509_CRL_print(out, x); if (crl_config.noout) { ret = 0; goto end; } if (crl_config.outformat == FORMAT_ASN1) i = (int) i2d_X509_CRL_bio(out, x); else if (crl_config.outformat == FORMAT_PEM) i = PEM_write_bio_X509_CRL(out, x); else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: BIO_free_all(out); BIO_free_all(bio_out); bio_out = NULL; X509_CRL_free(x); if (store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } return (ret); }
/* * This function verifies the validity of the certificate and the matching of the * other part's name with the certificate. * It also checks the sign validity of a message. * It returns -1 on generic error, -3 on mismatching on certificate, 1 on success. * It closes the passed file pointer fp (which should have already been opened). * The last argument is used to distinguish if we are initializing or accepting * a connection and so which is the correct name to verify. * After verifying, It leaves the public parameter of DH and the nonce of the * other part respectively in **pub_buf (which is allocated) and *nonce. */ int verify_name(FILE* fp,unsigned char *hello_buf,unsigned int hello_len,unsigned char *sign_buf,unsigned int sign_len,unsigned char** pub_buf,unsigned int *pubbuf_len,X509_STORE* str,int* nonce,int init){ int sheet_len,ret; uint32_t tmp; char read_mail[DIM_MAIL],temp_mail[DIM_MAIL],*cert_mail = NULL; X509_STORE_CTX* cert_ctx = NULL; EVP_PKEY* evp = EVP_PKEY_new(); EVP_MD_CTX* ctx = NULL; *pub_buf = NULL; if (!fp) { ret = -1; goto fail; } //We must come back to the start of fp rewind(fp); X509* cert = PEM_read_X509(fp,NULL,NULL,NULL); *pub_buf = NULL; //the following function is needed to correctly verify the certificate OpenSSL_add_all_algorithms(); if((cert_ctx=X509_STORE_CTX_new())==NULL){ ret = -1; goto fail; } if(X509_STORE_CTX_init(cert_ctx,str,cert,NULL)<=0){ ret = -1; goto fail; } if(X509_verify_cert(cert_ctx)==0){ //fprintf(stderr, "Error verifying certificate: %s\n", X509_verify_cert_error_string(X509_STORE_CTX_get_error(cert_ctx))); ret = -3; goto fail; } X509_STORE_CTX_cleanup(cert_ctx); X509_STORE_CTX_free(cert_ctx); cert_ctx = NULL; ctx = (EVP_MD_CTX*)calloc(1,sizeof(EVP_MD_CTX)); EVP_MD_CTX_init(ctx); evp = X509_get_pubkey(cert); if(EVP_VerifyInit(ctx,EVP_sha512())==0){ ret = -1; goto fail; } if(EVP_VerifyUpdate(ctx,hello_buf,hello_len)==0){ ret = -1; goto fail; } ret=EVP_VerifyFinal(ctx,sign_buf,sign_len,evp); if(ret == 0){ ret = -3; goto fail; } if (ret == -1) { goto fail; } rewind(fp); cert_mail = read_common_name(fp);//set it free later if(init == 1){ sscanf((char *)hello_buf,"%s%s",temp_mail,read_mail); } else{ sscanf((char *)hello_buf,"%s%s",read_mail,temp_mail); } sheet_len = strlen(temp_mail)+strlen(read_mail)+2; *pubbuf_len = hello_len - sheet_len; tmp = *((uint32_t *)(hello_buf+sheet_len)); *nonce = ntohl(tmp); sheet_len+=sizeof(tmp); *pub_buf = (unsigned char*)calloc(1,*pubbuf_len); memcpy(*pub_buf,hello_buf+sheet_len,*pubbuf_len); if(strlen(cert_mail)!=strlen(read_mail)){ ret = -3; goto fail; } if(strncmp(cert_mail,read_mail,strlen(cert_mail))!=0){ ret = -3; goto fail; } free(ctx); fclose(fp); EVP_PKEY_free(evp); free(cert_mail); return 1; fail: fclose(fp); if(cert_mail!=NULL){ free(cert_mail); } if(cert_ctx!=NULL){ X509_STORE_CTX_cleanup(cert_ctx); X509_STORE_CTX_free(cert_ctx); } if(ctx!=NULL){ free(ctx); } if(*pub_buf!=NULL){ free(*pub_buf); } EVP_PKEY_free(evp); return ret; }
/** * xmlSecOpenSSLX509StoreVerify: * @store: the pointer to X509 key data store klass. * @certs: the untrusted certificates stack. * @crls: the crls stack. * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. * * Verifies @certs list. * * Returns: pointer to the first verified certificate from @certs. */ X509* xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs, XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) { xmlSecOpenSSLX509StoreCtxPtr ctx; STACK_OF(X509)* certs2 = NULL; STACK_OF(X509_CRL)* crls2 = NULL; X509 * res = NULL; X509 * cert; X509 * err_cert = NULL; char buf[256]; int err = 0, depth; int i; int ret; xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL); xmlSecAssert2(certs != NULL, NULL); xmlSecAssert2(keyInfoCtx != NULL, NULL); ctx = xmlSecOpenSSLX509StoreGetCtx(store); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->xst != NULL, NULL); /* dup certs */ certs2 = sk_X509_dup(certs); if(certs2 == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "sk_X509_dup", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } /* add untrusted certs from the store */ if(ctx->untrusted != NULL) { for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) { ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i)); if(ret < 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "sk_X509_push", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } } /* dup crls but remove all non-verified */ if(crls != NULL) { crls2 = sk_X509_CRL_dup(crls); if(crls2 == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "sk_X509_CRL_dup", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } for(i = 0; i < sk_X509_CRL_num(crls2); ) { ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i)); if(ret == 1) { ++i; } else if(ret == 0) { (void)sk_X509_CRL_delete(crls2, i); } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCRL", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } } /* remove all revoked certs */ for(i = 0; i < sk_X509_num(certs2);) { cert = sk_X509_value(certs2, i); if(crls2 != NULL) { ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert); if(ret == 0) { (void)sk_X509_delete(certs2, i); continue; } else if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCertAgainstCrls", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } if(ctx->crls != NULL) { ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert); if(ret == 0) { (void)sk_X509_delete(certs2, i); continue; } else if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCertAgainstCrls", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } ++i; } /* get one cert after another and try to verify */ for(i = 0; i < sk_X509_num(certs2); ++i) { cert = sk_X509_value(certs2, i); if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) { X509_STORE_CTX xsc; #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) X509_VERIFY_PARAM * vpm = NULL; unsigned long vpm_flags = 0; vpm = X509_VERIFY_PARAM_new(); if(vpm == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_VERIFY_PARAM_new", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } vpm_flags = vpm->flags; /* vpm_flags &= (~X509_V_FLAG_X509_STRICT); */ vpm_flags &= (~X509_V_FLAG_CRL_CHECK); X509_VERIFY_PARAM_set_depth(vpm, 9); X509_VERIFY_PARAM_set_flags(vpm, vpm_flags); #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ X509_STORE_CTX_init (&xsc, ctx->xst, cert, certs2); if(keyInfoCtx->certsVerificationTime > 0) { #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) vpm_flags |= X509_V_FLAG_USE_CHECK_TIME; X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime); #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ X509_STORE_CTX_set_time(&xsc, 0, keyInfoCtx->certsVerificationTime); } #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) X509_STORE_CTX_set0_param(&xsc, vpm); #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ ret = X509_verify_cert(&xsc); err_cert = X509_STORE_CTX_get_current_cert(&xsc); err = X509_STORE_CTX_get_error(&xsc); depth = X509_STORE_CTX_get_error_depth(&xsc); X509_STORE_CTX_cleanup (&xsc); if(ret == 1) { res = cert; goto done; } else if(ret < 0) { const char* err_msg; buf[0] = '\0'; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); err_msg = X509_verify_cert_error_string(err); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_verify_cert", XMLSEC_ERRORS_R_CRYPTO_FAILED, "subj=%s;err=%d;msg=%s", xmlSecErrorsSafeString(buf), err, xmlSecErrorsSafeString(err_msg)); goto done; } else if(ret == 0) { const char* err_msg; buf[0] = '\0'; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); err_msg = X509_verify_cert_error_string(err); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_verify_cert", XMLSEC_ERRORS_R_CRYPTO_FAILED, "subj=%s;err=%d;msg=%s", xmlSecErrorsSafeString(buf), err, xmlSecErrorsSafeString(err_msg)); } } } /* if we came here then we found nothing. do we have any error? */ if((err != 0) && (err_cert != NULL)) { const char* err_msg; err_msg = X509_verify_cert_error_string(err); switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "err=%d;msg=%s;issuer=%s", err, xmlSecErrorsSafeString(err_msg), xmlSecErrorsSafeString(buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); break; default: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); } } done: if(certs2 != NULL) { sk_X509_free(certs2); } if(crls2 != NULL) { sk_X509_CRL_free(crls2); } return(res); }