X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fapps.c;h=1ad0e137d12adefa5d15b802f1b58c004012dd4e;hp=60bd7ef343a615f5410e05fadc575858c8cf6d02;hb=0db46a7dd79cac420c08d68fc782d561e7927af1;hpb=0a39d8f2074aa96b48a76e01bd246f6beb778439 diff --git a/apps/apps.c b/apps/apps.c index 60bd7ef343..1ad0e137d1 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -109,12 +109,22 @@ * */ +#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +#define _POSIX_C_SOURCE 2 /* On VMS, you need to define this to get + the declaration of fileno(). The value + 2 is to make sure no function defined + in POSIX-2 is left undefined. */ +#endif #include #include #include +#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB) +#include +#endif #include #include #include +#include #include #include #include @@ -129,6 +139,9 @@ #include #endif #include +#ifndef OPENSSL_NO_JPAKE +#include +#endif #define NON_MAIN #include "apps.h" @@ -244,17 +257,12 @@ int args_from_file(char *file, int *argc, char **argv[]) int str2fmt(char *s) { + if (s == NULL) + return FORMAT_UNDEF; if ((*s == 'D') || (*s == 'd')) return(FORMAT_ASN1); else if ((*s == 'T') || (*s == 't')) return(FORMAT_TEXT); - else if ((*s == 'P') || (*s == 'p')) - { - if (s[1] == 'V' || s[1] == 'v') - return FORMAT_PVK; - else - return(FORMAT_PEM); - } else if ((*s == 'N') || (*s == 'n')) return(FORMAT_NETSCAPE); else if ((*s == 'S') || (*s == 's')) @@ -267,6 +275,15 @@ int str2fmt(char *s) return(FORMAT_PKCS12); else if ((*s == 'E') || (*s == 'e')) return(FORMAT_ENGINE); + else if ((*s == 'H') || (*s == 'h')) + return FORMAT_HTTP; + else if ((*s == 'P') || (*s == 'p')) + { + if (s[1] == 'V' || s[1] == 'v') + return FORMAT_PVK; + else + return(FORMAT_PEM); + } else return(FORMAT_UNDEF); } @@ -364,13 +381,12 @@ void program_name(char *in, char *out, int size) int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) { - int num,len,i; + int num,i; char *p; *argc=0; *argv=NULL; - len=strlen(buf); i=0; if (arg->count == 0) { @@ -769,12 +785,80 @@ static int load_pkcs12(BIO *err, BIO *in, const char *desc, return ret; } +int load_cert_crl_http(const char *url, BIO *err, + X509 **pcert, X509_CRL **pcrl) + { + char *host = NULL, *port = NULL, *path = NULL; + BIO *bio = NULL; + OCSP_REQ_CTX *rctx = NULL; + int use_ssl, rv = 0; + if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) + goto err; + if (use_ssl) + { + if (err) + BIO_puts(err, "https not supported\n"); + goto err; + } + bio = BIO_new_connect(host); + if (!bio || !BIO_set_conn_port(bio, port)) + goto err; + rctx = OCSP_REQ_CTX_new(bio, 1024); + if (!rctx) + goto err; + if (!OCSP_REQ_CTX_http(rctx, "GET", path)) + goto err; + if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host)) + goto err; + if (pcert) + { + do + { + rv = X509_http_nbio(rctx, pcert); + } + while (rv == -1); + } + else + { + do + { + rv = X509_CRL_http_nbio(rctx, pcrl); + } while (rv == -1); + } + + err: + if (host) + OPENSSL_free(host); + if (path) + OPENSSL_free(path); + if (port) + OPENSSL_free(port); + if (bio) + BIO_free_all(bio); + if (rctx) + OCSP_REQ_CTX_free(rctx); + if (rv != 1) + { + if (bio && err) + BIO_printf(bio_err, "Error loading %s from %s\n", + pcert ? "certificate" : "CRL", url); + ERR_print_errors(bio_err); + } + return rv; + } + X509 *load_cert(BIO *err, const char *file, int format, const char *pass, ENGINE *e, const char *cert_descrip) { X509 *x=NULL; BIO *cert; + if (format == FORMAT_HTTP) + { + load_cert_crl_http(file, err, &x, NULL); + return x; + } + if ((cert=BIO_new(BIO_s_file())) == NULL) { ERR_print_errors(err); @@ -784,7 +868,9 @@ X509 *load_cert(BIO *err, const char *file, int format, if (file == NULL) { #ifdef _IONBF +# ifndef OPENSSL_NO_SETVBUF_IONBF setvbuf(stdin, NULL, _IONBF, 0); +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #endif BIO_set_fp(cert,stdin,BIO_NOCLOSE); } @@ -843,6 +929,55 @@ end: return(x); } +X509_CRL *load_crl(char *infile, int format) + { + X509_CRL *x=NULL; + BIO *in=NULL; + + if (format == FORMAT_HTTP) + { + load_cert_crl_http(infile, bio_err, NULL, &x); + return x; + } + + in=BIO_new(BIO_s_file()); + if (in == NULL) + { + ERR_print_errors(bio_err); + goto end; + } + + if (infile == NULL) + BIO_set_fp(in,stdin,BIO_NOCLOSE); + else + { + if (BIO_read_filename(in,infile) <= 0) + { + perror(infile); + goto end; + } + } + if (format == FORMAT_ASN1) + x=d2i_X509_CRL_bio(in,NULL); + else if (format == FORMAT_PEM) + x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); + else { + BIO_printf(bio_err,"bad input format specified for input crl\n"); + goto end; + } + if (x == NULL) + { + BIO_printf(bio_err,"unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + +end: + BIO_free(in); + return(x); + } + + EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip) { @@ -862,10 +997,17 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, if (format == FORMAT_ENGINE) { if (!e) - BIO_printf(bio_err,"no engine specified\n"); + BIO_printf(err,"no engine specified\n"); else + { pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); + if (!pkey) + { + BIO_printf(err,"cannot load %s from engine\n",key_descrip); + ERR_print_errors(err); + } + } goto end; } #endif @@ -878,7 +1020,9 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, if (file == NULL && maybe_stdin) { #ifdef _IONBF +# ifndef OPENSSL_NO_SETVBUF_IONBF setvbuf(stdin, NULL, _IONBF, 0); +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #endif BIO_set_fp(key,stdin,BIO_NOCLOSE); } @@ -910,11 +1054,13 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, &pkey, NULL, NULL)) goto end; } +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) else if (format == FORMAT_MSBLOB) pkey = b2i_PrivateKey_bio(key); else if (format == FORMAT_PVK) pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, &cb_data); +#endif else { BIO_printf(err,"bad input format specified for key file\n"); @@ -922,8 +1068,11 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, } end: if (key != NULL) BIO_free(key); - if (pkey == NULL) + if (pkey == NULL) + { BIO_printf(err,"unable to load %s\n", key_descrip); + ERR_print_errors(err); + } return(pkey); } @@ -962,7 +1111,9 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, if (file == NULL && maybe_stdin) { #ifdef _IONBF +# ifndef OPENSSL_NO_SETVBUF_IONBF setvbuf(stdin, NULL, _IONBF, 0); +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #endif BIO_set_fp(key,stdin,BIO_NOCLOSE); } @@ -978,6 +1129,7 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, { pkey=d2i_PUBKEY_bio(key, NULL); } +#ifndef OPENSSL_NO_RSA else if (format == FORMAT_ASN1RSA) { RSA *rsa; @@ -1007,7 +1159,7 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, else pkey = NULL; } - +#endif else if (format == FORMAT_PEM) { pkey=PEM_read_bio_PUBKEY(key,NULL, @@ -1017,8 +1169,10 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) pkey = load_netscape_key(err, key, file, key_descrip, format); #endif +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) else if (format == FORMAT_MSBLOB) pkey = b2i_PublicKey_bio(key); +#endif else { BIO_printf(err,"bad input format specified for key file\n"); @@ -1077,76 +1231,122 @@ error: } #endif /* ndef OPENSSL_NO_RC4 */ -STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, const char *cert_descrip) +static int load_certs_crls(BIO *err, const char *file, int format, + const char *pass, ENGINE *e, const char *desc, + STACK_OF(X509) **pcerts, STACK_OF(X509_CRL) **pcrls) { - BIO *certs; int i; - STACK_OF(X509) *othercerts = NULL; - STACK_OF(X509_INFO) *allcerts = NULL; + BIO *bio; + STACK_OF(X509_INFO) *xis = NULL; X509_INFO *xi; PW_CB_DATA cb_data; + int rv = 0; cb_data.password = pass; cb_data.prompt_info = file; - if((certs = BIO_new(BIO_s_file())) == NULL) + if (format != FORMAT_PEM) { - ERR_print_errors(err); - goto end; + BIO_printf(err,"bad input format specified for %s\n", desc); + return 0; } if (file == NULL) - BIO_set_fp(certs,stdin,BIO_NOCLOSE); + bio = BIO_new_fp(stdin,BIO_NOCLOSE); else + bio = BIO_new_file(file, "r"); + + if (bio == NULL) { - if (BIO_read_filename(certs,file) <= 0) - { - BIO_printf(err, "Error opening %s %s\n", - cert_descrip, file); - ERR_print_errors(err); + BIO_printf(err, "Error opening %s %s\n", + desc, file ? file : "stdin"); + ERR_print_errors(err); + return 0; + } + + xis = PEM_X509_INFO_read_bio(bio, NULL, + (pem_password_cb *)password_callback, &cb_data); + + BIO_free(bio); + + if (pcerts) + { + *pcerts = sk_X509_new_null(); + if (!*pcerts) goto end; - } } - if (format == FORMAT_PEM) + if (pcrls) { - othercerts = sk_X509_new_null(); - if(!othercerts) - { - sk_X509_free(othercerts); - othercerts = NULL; + *pcrls = sk_X509_CRL_new_null(); + if (!*pcrls) goto end; + } + + for(i = 0; i < sk_X509_INFO_num(xis); i++) + { + xi = sk_X509_INFO_value (xis, i); + if (xi->x509 && pcerts) + { + if (!sk_X509_push(*pcerts, xi->x509)) + goto end; + xi->x509 = NULL; } - allcerts = PEM_X509_INFO_read_bio(certs, NULL, - (pem_password_cb *)password_callback, &cb_data); - for(i = 0; i < sk_X509_INFO_num(allcerts); i++) + if (xi->crl && pcrls) { - xi = sk_X509_INFO_value (allcerts, i); - if (xi->x509) - { - sk_X509_push(othercerts, xi->x509); - xi->x509 = NULL; - } + if (!sk_X509_CRL_push(*pcrls, xi->crl)) + goto end; + xi->crl = NULL; } - goto end; } - else { - BIO_printf(err,"bad input format specified for %s\n", - cert_descrip); - goto end; - } -end: - if (othercerts == NULL) + + if (pcerts && sk_X509_num(*pcerts) > 0) + rv = 1; + + if (pcrls && sk_X509_CRL_num(*pcrls) > 0) + rv = 1; + + end: + + if (xis) + sk_X509_INFO_pop_free(xis, X509_INFO_free); + + if (rv == 0) { - BIO_printf(err,"unable to load certificates\n"); + if (pcerts) + { + sk_X509_pop_free(*pcerts, X509_free); + *pcerts = NULL; + } + if (pcrls) + { + sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); + *pcrls = NULL; + } + BIO_printf(err,"unable to load %s\n", + pcerts ? "certificates" : "CRLs"); ERR_print_errors(err); } - if (allcerts) sk_X509_INFO_pop_free(allcerts, X509_INFO_free); - if (certs != NULL) BIO_free(certs); - return(othercerts); + return rv; } +STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, + const char *pass, ENGINE *e, const char *desc) + { + STACK_OF(X509) *certs; + if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL)) + return NULL; + return certs; + } + +STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, + const char *pass, ENGINE *e, const char *desc) + { + STACK_OF(X509_CRL) *crls; + if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls)) + return NULL; + return crls; + } #define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) /* Return error for unknown extensions */ @@ -1433,6 +1633,10 @@ ENGINE *setup_engine(BIO *err, const char *engine, int debug) int load_config(BIO *err, CONF *cnf) { + static int load_config_called = 0; + if (load_config_called) + return 1; + load_config_called = 1; if (!cnf) cnf = config; if (!cnf) @@ -1466,7 +1670,7 @@ char *make_config_name() return p; } -static unsigned long index_serial_hash(const char **a) +static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) { const char *n; @@ -1475,7 +1679,7 @@ static unsigned long index_serial_hash(const char **a) return(lh_strhash(n)); } -static int index_serial_cmp(const char **a, const char **b) +static int index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) { const char *aa,*bb; @@ -1487,17 +1691,16 @@ static int index_serial_cmp(const char **a, const char **b) static int index_name_qual(char **a) { return(a[0][0] == 'V'); } -static unsigned long index_name_hash(const char **a) +static unsigned long index_name_hash(const OPENSSL_CSTRING *a) { return(lh_strhash(a[DB_name])); } -int index_name_cmp(const char **a, const char **b) - { return(strcmp(a[DB_name], - b[DB_name])); } +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) + { return(strcmp(a[DB_name], b[DB_name])); } -static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **) -static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **) -static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **) -static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **) +static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) #undef BSIZE #define BSIZE 256 @@ -1730,10 +1933,7 @@ CA_DB *load_index(char *dbfile, DB_ATTR *db_attr) goto err; } if ((tmpdb = TXT_DB_read(in,DB_NUMBER)) == NULL) - { - if (tmpdb != NULL) TXT_DB_free(tmpdb); goto err; - } #ifndef OPENSSL_SYS_VMS BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile); @@ -1794,8 +1994,8 @@ CA_DB *load_index(char *dbfile, DB_ATTR *db_attr) int index_index(CA_DB *db) { if (!TXT_DB_create_index(db->db, DB_serial, NULL, - LHASH_HASH_FN(index_serial_hash), - LHASH_COMP_FN(index_serial_cmp))) + LHASH_HASH_FN(index_serial), + LHASH_COMP_FN(index_serial))) { BIO_printf(bio_err, "error creating serial number index:(%ld,%ld,%ld)\n", @@ -1805,8 +2005,8 @@ int index_index(CA_DB *db) if (db->attributes.unique_subject && !TXT_DB_create_index(db->db, DB_name, index_name_qual, - LHASH_HASH_FN(index_name_hash), - LHASH_COMP_FN(index_name_cmp))) + LHASH_HASH_FN(index_name), + LHASH_COMP_FN(index_name))) { BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n", db->db->error,db->db->arg1,db->db->arg2); @@ -2022,7 +2222,7 @@ int parse_yesno(const char *str, int def) case 'y': /* yes */ case 'Y': /* YES */ case '1': /* 1 */ - ret = 0; + ret = 1; break; default: ret = def; @@ -2155,6 +2355,7 @@ X509_NAME *parse_name(char *subject, long chtype, int multirdn) OPENSSL_free(ne_values); OPENSSL_free(ne_types); OPENSSL_free(buf); + OPENSSL_free(mval); return n; error: @@ -2163,6 +2364,8 @@ error: OPENSSL_free(ne_values); if (ne_types) OPENSSL_free(ne_types); + if (mval) + OPENSSL_free(mval); if (buf) OPENSSL_free(buf); return NULL; @@ -2174,9 +2377,11 @@ int args_verify(char ***pargs, int *pargc, ASN1_OBJECT *otmp = NULL; unsigned long flags = 0; int i; - int purpose = 0; + int purpose = 0, depth = -1; char **oldargs = *pargs; char *arg = **pargs, *argn = (*pargs)[1]; + const X509_VERIFY_PARAM *vpm = NULL; + time_t at_time = 0; if (!strcmp(arg, "-policy")) { if (!argn) @@ -2214,6 +2419,57 @@ int args_verify(char ***pargs, int *pargc, } (*pargs)++; } + else if (strcmp(arg,"-verify_name") == 0) + { + if (!argn) + *badarg = 1; + else + { + vpm = X509_VERIFY_PARAM_lookup(argn); + if(!vpm) + { + BIO_printf(err, "unrecognized verify name\n"); + *badarg = 1; + } + } + (*pargs)++; + } + else if (strcmp(arg,"-verify_depth") == 0) + { + if (!argn) + *badarg = 1; + else + { + depth = atoi(argn); + if(depth < 0) + { + BIO_printf(err, "invalid depth\n"); + *badarg = 1; + } + } + (*pargs)++; + } + else if (strcmp(arg,"-attime") == 0) + { + if (!argn) + *badarg = 1; + else + { + long timestamp; + /* interpret the -attime argument as seconds since + * Epoch */ + if (sscanf(argn, "%li", ×tamp) != 1) + { + BIO_printf(bio_err, + "Error parsing timestamp %s\n", + argn); + *badarg = 1; + } + /* on some platforms time_t may be a float */ + at_time = (time_t) timestamp; + } + (*pargs)++; + } else if (!strcmp(arg, "-ignore_critical")) flags |= X509_V_FLAG_IGNORE_CRITICAL; else if (!strcmp(arg, "-issuer_checks")) @@ -2226,10 +2482,28 @@ int args_verify(char ***pargs, int *pargc, flags |= X509_V_FLAG_POLICY_CHECK; else if (!strcmp(arg, "-explicit_policy")) flags |= X509_V_FLAG_EXPLICIT_POLICY; + else if (!strcmp(arg, "-inhibit_any")) + flags |= X509_V_FLAG_INHIBIT_ANY; + else if (!strcmp(arg, "-inhibit_map")) + flags |= X509_V_FLAG_INHIBIT_MAP; else if (!strcmp(arg, "-x509_strict")) flags |= X509_V_FLAG_X509_STRICT; + else if (!strcmp(arg, "-extended_crl")) + flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT; + else if (!strcmp(arg, "-use_deltas")) + flags |= X509_V_FLAG_USE_DELTAS; else if (!strcmp(arg, "-policy_print")) flags |= X509_V_FLAG_NOTIFY_POLICY; + else if (!strcmp(arg, "-check_ss_sig")) + flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; + else if (!strcmp(arg, "-trusted_first")) + flags |= X509_V_FLAG_TRUSTED_FIRST; + else if (!strcmp(arg, "-suiteB_128_only")) + flags |= X509_V_FLAG_SUITEB_128_LOS_ONLY; + else if (!strcmp(arg, "-suiteB_128")) + flags |= X509_V_FLAG_SUITEB_128_LOS; + else if (!strcmp(arg, "-suiteB_192")) + flags |= X509_V_FLAG_SUITEB_192_LOS; else return 0; @@ -2247,6 +2521,9 @@ int args_verify(char ***pargs, int *pargc, goto end; } + if (vpm) + X509_VERIFY_PARAM_set1(*pm, vpm); + if (otmp) X509_VERIFY_PARAM_add0_policy(*pm, otmp); if (flags) @@ -2255,6 +2532,12 @@ int args_verify(char ***pargs, int *pargc, if (purpose) X509_VERIFY_PARAM_set_purpose(*pm, purpose); + if (depth >= 0) + X509_VERIFY_PARAM_set_depth(*pm, depth); + + if (at_time) + X509_VERIFY_PARAM_set_time(*pm, at_time); + end: (*pargs)++; @@ -2266,6 +2549,61 @@ int args_verify(char ***pargs, int *pargc, } +/* Read whole contents of a BIO into an allocated memory buffer and + * return it. + */ + +int bio_to_mem(unsigned char **out, int maxlen, BIO *in) + { + BIO *mem; + int len, ret; + unsigned char tbuf[1024]; + mem = BIO_new(BIO_s_mem()); + if (!mem) + return -1; + for(;;) + { + if ((maxlen != -1) && maxlen < 1024) + len = maxlen; + else + len = 1024; + len = BIO_read(in, tbuf, len); + if (len <= 0) + break; + if (BIO_write(mem, tbuf, len) != len) + { + BIO_free(mem); + return -1; + } + maxlen -= len; + + if (maxlen == 0) + break; + } + ret = BIO_get_mem_data(mem, (char **)out); + BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); + BIO_free(mem); + return ret; + } + +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value) + { + int rv; + char *stmp, *vtmp = NULL; + stmp = BUF_strdup(value); + if (!stmp) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp) + { + *vtmp = 0; + vtmp++; + } + rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); + OPENSSL_free(stmp); + return rv; + } + static void nodes_print(BIO *out, const char *name, STACK_OF(X509_POLICY_NODE) *nodes) { @@ -2307,6 +2645,303 @@ void policies_print(BIO *out, X509_STORE_CTX *ctx) BIO_free(out); } +#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) + +static JPAKE_CTX *jpake_init(const char *us, const char *them, + const char *secret) + { + BIGNUM *p = NULL; + BIGNUM *g = NULL; + BIGNUM *q = NULL; + BIGNUM *bnsecret = BN_new(); + JPAKE_CTX *ctx; + + /* Use a safe prime for p (that we found earlier) */ + BN_hex2bn(&p, "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F"); + g = BN_new(); + BN_set_word(g, 2); + q = BN_new(); + BN_rshift1(q, p); + + BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret); + + ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret); + BN_free(bnsecret); + BN_free(q); + BN_free(g); + BN_free(p); + + return ctx; + } + +static void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p) + { + BN_print(conn, p->gx); + BIO_puts(conn, "\n"); + BN_print(conn, p->zkpx.gr); + BIO_puts(conn, "\n"); + BN_print(conn, p->zkpx.b); + BIO_puts(conn, "\n"); + } + +static void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx) + { + JPAKE_STEP1 s1; + + JPAKE_STEP1_init(&s1); + JPAKE_STEP1_generate(&s1, ctx); + jpake_send_part(bconn, &s1.p1); + jpake_send_part(bconn, &s1.p2); + (void)BIO_flush(bconn); + JPAKE_STEP1_release(&s1); + } + +static void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx) + { + JPAKE_STEP2 s2; + + JPAKE_STEP2_init(&s2); + JPAKE_STEP2_generate(&s2, ctx); + jpake_send_part(bconn, &s2); + (void)BIO_flush(bconn); + JPAKE_STEP2_release(&s2); + } + +static void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx) + { + JPAKE_STEP3A s3a; + + JPAKE_STEP3A_init(&s3a); + JPAKE_STEP3A_generate(&s3a, ctx); + BIO_write(bconn, s3a.hhk, sizeof s3a.hhk); + (void)BIO_flush(bconn); + JPAKE_STEP3A_release(&s3a); + } + +static void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx) + { + JPAKE_STEP3B s3b; + + JPAKE_STEP3B_init(&s3b); + JPAKE_STEP3B_generate(&s3b, ctx); + BIO_write(bconn, s3b.hk, sizeof s3b.hk); + (void)BIO_flush(bconn); + JPAKE_STEP3B_release(&s3b); + } + +static void readbn(BIGNUM **bn, BIO *bconn) + { + char buf[10240]; + int l; + + l = BIO_gets(bconn, buf, sizeof buf); + assert(l > 0); + assert(buf[l-1] == '\n'); + buf[l-1] = '\0'; + BN_hex2bn(bn, buf); + } + +static void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn) + { + readbn(&p->gx, bconn); + readbn(&p->zkpx.gr, bconn); + readbn(&p->zkpx.b, bconn); + } + +static void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn) + { + JPAKE_STEP1 s1; + + JPAKE_STEP1_init(&s1); + jpake_receive_part(&s1.p1, bconn); + jpake_receive_part(&s1.p2, bconn); + if(!JPAKE_STEP1_process(ctx, &s1)) + { + ERR_print_errors(bio_err); + exit(1); + } + JPAKE_STEP1_release(&s1); + } + +static void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn) + { + JPAKE_STEP2 s2; + + JPAKE_STEP2_init(&s2); + jpake_receive_part(&s2, bconn); + if(!JPAKE_STEP2_process(ctx, &s2)) + { + ERR_print_errors(bio_err); + exit(1); + } + JPAKE_STEP2_release(&s2); + } + +static void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn) + { + JPAKE_STEP3A s3a; + int l; + + JPAKE_STEP3A_init(&s3a); + l = BIO_read(bconn, s3a.hhk, sizeof s3a.hhk); + assert(l == sizeof s3a.hhk); + if(!JPAKE_STEP3A_process(ctx, &s3a)) + { + ERR_print_errors(bio_err); + exit(1); + } + JPAKE_STEP3A_release(&s3a); + } + +static void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn) + { + JPAKE_STEP3B s3b; + int l; + + JPAKE_STEP3B_init(&s3b); + l = BIO_read(bconn, s3b.hk, sizeof s3b.hk); + assert(l == sizeof s3b.hk); + if(!JPAKE_STEP3B_process(ctx, &s3b)) + { + ERR_print_errors(bio_err); + exit(1); + } + JPAKE_STEP3B_release(&s3b); + } + +void jpake_client_auth(BIO *out, BIO *conn, const char *secret) + { + JPAKE_CTX *ctx; + BIO *bconn; + + BIO_puts(out, "Authenticating with JPAKE\n"); + + ctx = jpake_init("client", "server", secret); + + bconn = BIO_new(BIO_f_buffer()); + BIO_push(bconn, conn); + + jpake_send_step1(bconn, ctx); + jpake_receive_step1(ctx, bconn); + jpake_send_step2(bconn, ctx); + jpake_receive_step2(ctx, bconn); + jpake_send_step3a(bconn, ctx); + jpake_receive_step3b(ctx, bconn); + + BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); + + psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); + + BIO_pop(bconn); + BIO_free(bconn); + + JPAKE_CTX_free(ctx); + } + +void jpake_server_auth(BIO *out, BIO *conn, const char *secret) + { + JPAKE_CTX *ctx; + BIO *bconn; + + BIO_puts(out, "Authenticating with JPAKE\n"); + + ctx = jpake_init("server", "client", secret); + + bconn = BIO_new(BIO_f_buffer()); + BIO_push(bconn, conn); + + jpake_receive_step1(ctx, bconn); + jpake_send_step1(bconn, ctx); + jpake_receive_step2(ctx, bconn); + jpake_send_step2(bconn, ctx); + jpake_receive_step3a(ctx, bconn); + jpake_send_step3b(bconn, ctx); + + BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); + + psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); + + BIO_pop(bconn); + BIO_free(bconn); + + JPAKE_CTX_free(ctx); + } + +#endif + +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +/* next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL termianted string like "abc,def,ghi" + * + * returns: a malloced buffer or NULL on failure. + */ +unsigned char *next_protos_parse(unsigned short *outlen, const char *in) + { + size_t len; + unsigned char *out; + size_t i, start = 0; + + len = strlen(in); + if (len >= 65535) + return NULL; + + out = OPENSSL_malloc(strlen(in) + 1); + if (!out) + return NULL; + + for (i = 0; i <= len; ++i) + { + if (i == len || in[i] == ',') + { + if (i - start > 255) + { + OPENSSL_free(out); + return NULL; + } + out[start] = i - start; + start = i + 1; + } + else + out[i+1] = in[i]; + } + + *outlen = len + 1; + return out; + } +#endif /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */ + +void print_cert_checks(BIO *bio, X509 *x, + const unsigned char *checkhost, + const unsigned char *checkemail, + const char *checkip) + { + if (x == NULL) + return; + if (checkhost) + { + BIO_printf(bio, "Hostname %s does%s match certificate\n", + checkhost, X509_check_host(x, checkhost, 0, 0) + ? "" : " NOT"); + } + + if (checkemail) + { + BIO_printf(bio, "Email %s does%s match certificate\n", + checkemail, X509_check_email(x, checkemail, 0, + 0) ? "" : " NOT"); + } + + if (checkip) + { + BIO_printf(bio, "IP %s does%s match certificate\n", + checkip, X509_check_ip_asc(x, checkip, + 0) ? "" : " NOT"); + } + } + /* * Platform-specific sections */ @@ -2375,6 +3010,7 @@ double app_tminterval(int stop,int usertime) FILETIME now; double ret=0; static ULARGE_INTEGER tmstart; + static int warning=1; #ifdef _WIN32_WINNT static HANDLE proc=NULL; @@ -2395,6 +3031,13 @@ double app_tminterval(int stop,int usertime) #endif { SYSTEMTIME systime; + + if (usertime && warning) + { + BIO_printf(bio_err,"To get meaningful results, run " + "this program on idle system.\n"); + warning=0; + } GetSystemTime(&systime); SystemTimeToFileTime(&systime,&now); } @@ -2410,12 +3053,101 @@ double app_tminterval(int stop,int usertime) tmstop.u.LowPart = now.dwLowDateTime; tmstop.u.HighPart = now.dwHighDateTime; - ret = (tmstop.QuadPart - tmstart.QuadPart)*1e-7; + ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart)*1e-7; } return (ret); } +#elif defined(OPENSSL_SYS_NETWARE) +#include + +double app_tminterval(int stop,int usertime) + { + double ret=0; + static clock_t tmstart; + static int warning=1; + + if (usertime && warning) + { + BIO_printf(bio_err,"To get meaningful results, run " + "this program on idle system.\n"); + warning=0; + } + + if (stop==TM_START) tmstart = clock(); + else ret = (clock()-tmstart)/(double)CLOCKS_PER_SEC; + + return (ret); + } + +#elif defined(OPENSSL_SYSTEM_VXWORKS) +#include + +double app_tminterval(int stop,int usertime) + { + double ret=0; +#ifdef CLOCK_REALTIME + static struct timespec tmstart; + struct timespec now; +#else + static unsigned long tmstart; + unsigned long now; +#endif + static int warning=1; + + if (usertime && warning) + { + BIO_printf(bio_err,"To get meaningful results, run " + "this program on idle system.\n"); + warning=0; + } + +#ifdef CLOCK_REALTIME + clock_gettime(CLOCK_REALTIME,&now); + if (stop==TM_START) tmstart = now; + else ret = ( (now.tv_sec+now.tv_nsec*1e-9) + - (tmstart.tv_sec+tmstart.tv_nsec*1e-9) ); +#else + now = tickGet(); + if (stop==TM_START) tmstart = now; + else ret = (now - tmstart)/(double)sysClkRateGet(); +#endif + return (ret); + } + +#elif defined(OPENSSL_SYSTEM_VMS) +#include +#include + +double app_tminterval(int stop,int usertime) + { + static clock_t tmstart; + double ret = 0; + clock_t now; +#ifdef __TMS + struct tms rus; + + now = times(&rus); + if (usertime) now = rus.tms_utime; +#else + if (usertime) + now = clock(); /* sum of user and kernel times */ + else { + struct timeval tv; + gettimeofday(&tv,NULL); + now = (clock_t)( + (unsigned long long)tv.tv_sec*CLK_TCK + + (unsigned long long)tv.tv_usec*(1000000/CLK_TCK) + ); + } +#endif + if (stop==TM_START) tmstart = now; + else ret = (now - tmstart)/(double)(CLK_TCK); + + return (ret); + } + #elif defined(_SC_CLK_TCK) /* by means of unistd.h */ #include @@ -2428,8 +3160,12 @@ double app_tminterval(int stop,int usertime) if (usertime) now = rus.tms_utime; - if (stop==TMSTART) tmstart = now; - else ret = (now - tmstart)/(double)sysconf(_SC_CLK_TCK); + if (stop==TM_START) tmstart = now; + else + { + long int tck = sysconf(_SC_CLK_TCK); + ret = (now - tmstart)/(double)tck; + } return (ret); } @@ -2445,10 +3181,10 @@ double app_tminterval(int stop,int usertime) struct timeval now; static struct timeval tmstart; - if (usertime) getrusage(RUSAGE_SELF,&rus), now = rus.ru_time; + if (usertime) getrusage(RUSAGE_SELF,&rus), now = rus.ru_utime; else gettimeofday(&now,NULL); - if (stop==TMSTART) tmstart = now; + if (stop==TM_START) tmstart = now; else ret = ( (now.tv_sec+now.tv_usec*1e-6) - (tmstart.tv_sec+tmstart.tv_usec*1e-6) ); @@ -2520,7 +3256,7 @@ int raw_read_stdin(void *buf,int siz) #endif #if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) -int raw_write_stdout(void *buf,int siz) +int raw_write_stdout(const void *buf,int siz) { DWORD n; if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,siz,&n,NULL))