Beispiel #1
0
EAC_CTX *
EAC_CTX_new(void)
{
    EAC_CTX *ctx = OPENSSL_malloc(sizeof(EAC_CTX));
    if (!ctx)
        return NULL;

    ctx->bn_ctx = BN_CTX_new();
    ctx->ca_ctxs = (STACK_OF(CA_CTX *)) sk_new_null();
    ctx->cipher_ctx = EVP_CIPHER_CTX_new();
    ctx->md_ctx = EVP_MD_CTX_create();
    ctx->pace_ctxs = (STACK_OF(PACE_CTX *)) sk_new_null();
    ctx->ri_ctxs = (STACK_OF(RI_CTX *)) sk_new_null();
    ctx->ssc = BN_new();
    ctx->ta_ctx = TA_CTX_new();

    if (!ctx->bn_ctx || !ctx->md_ctx || !ctx->pace_ctxs
            || !ctx->ta_ctx || !ctx->ca_ctxs || !ctx->cipher_ctx
            || !ctx->ri_ctxs || !ctx->ssc)
        goto err;

    BN_CTX_init(ctx->bn_ctx);
    EVP_CIPHER_CTX_init(ctx->cipher_ctx);
    ctx->ca_ctx = NULL;
    ctx->key_ctx = NULL;
    ctx->pace_ctx = NULL;
    ctx->ri_ctx = NULL;
    ctx->tr_version = EAC_TR_VERSION_2_02;

    return ctx;

err:
    EAC_CTX_clear_free(ctx);
    return NULL;
}
Beispiel #2
0
int CRYPTO_get_new_lockid(char *name)
	{
	char *str;
	int i;

#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
	/* A hack to make Visual C++ 5.0 work correctly when linking as
	 * a DLL using /MT. Without this, the application cannot use
	 * and floating point printf's.
	 * It also seems to be needed for Visual C 1.5 (win16) */
	SSLeay_MSVC5_hack=(double)name[0]*(double)name[1];
#endif

	if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL))
		{
		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
		return(0);
		}
	if ((str=BUF_strdup(name)) == NULL)
		{
		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
		return(0);
		}
	i=sk_push(app_locks,str);
	if (!i)
		OPENSSL_free(str);
	else
		i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */
	return(i);
	}
Beispiel #3
0
int MAIN(int argc, char **argv)
	{
	int i,badops=0,offset=0,ret=1,j;
	unsigned int length=0;
	long num,tmplen;
	BIO *in=NULL,*out=NULL,*b64=NULL, *derout = NULL;
	int informat,indent=0, noout = 0, dump = 0;
	char *infile=NULL,*str=NULL,*prog,*oidfile=NULL, *derfile=NULL;
	unsigned char *tmpbuf;
	BUF_MEM *buf=NULL;
	STACK *osk=NULL;
	ASN1_TYPE *at=NULL;

	informat=FORMAT_PEM;

	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

	prog=argv[0];
	argc--;
	argv++;
	if ((osk=sk_new_null()) == NULL)
		{
		BIO_printf(bio_err,"Memory allocation failure\n");
		goto end;
		}
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			derfile= *(++argv);
			}
		else if (strcmp(*argv,"-i") == 0)
			{
			indent=1;
			}
		else if (strcmp(*argv,"-noout") == 0) noout = 1;
		else if (strcmp(*argv,"-oid") == 0)
			{
			if (--argc < 1) goto bad;
			oidfile= *(++argv);
			}
		else if (strcmp(*argv,"-offset") == 0)
			{
			if (--argc < 1) goto bad;
			offset= atoi(*(++argv));
			}
		else if (strcmp(*argv,"-length") == 0)
			{
			if (--argc < 1) goto bad;
			length= atoi(*(++argv));
			if (length == 0) goto bad;
			}
		else if (strcmp(*argv,"-dump") == 0)
			{
			dump= -1;
			}
		else if (strcmp(*argv,"-dlimit") == 0)
			{
			if (--argc < 1) goto bad;
			dump= atoi(*(++argv));
			if (dump <= 0) goto bad;
			}
		else if (strcmp(*argv,"-strparse") == 0)
			{
			if (--argc < 1) goto bad;
			sk_push(osk,*(++argv));
			}
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] <infile\n",prog);
		BIO_printf(bio_err,"where options are\n");
		BIO_printf(bio_err," -inform arg   input format - one of DER TXT PEM\n");
		BIO_printf(bio_err," -in arg       input file\n");
		BIO_printf(bio_err," -out arg      output file (output format is always DER\n");
		BIO_printf(bio_err," -noout arg    don't produce any output\n");
		BIO_printf(bio_err," -offset arg   offset into file\n");
		BIO_printf(bio_err," -length arg   length of section in file\n");
		BIO_printf(bio_err," -i            indent entries\n");
		BIO_printf(bio_err," -dump         dump unknown data in hex form\n");
		BIO_printf(bio_err," -dlimit arg   dump the first arg bytes of unknown data in hex form\n");
		BIO_printf(bio_err," -oid file     file of extra oid definitions\n");
		BIO_printf(bio_err," -strparse offset\n");
		BIO_printf(bio_err,"               a series of these can be used to 'dig' into multiple\n");
		BIO_printf(bio_err,"               ASN1 blob wrappings\n");
		goto end;
		}

	ERR_load_crypto_strings();

	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		{
		ERR_print_errors(bio_err);
		goto end;
		}
	BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
#ifdef VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	out = BIO_push(tmpbio, out);
	}
#endif

	if (oidfile != NULL)
		{
		if (BIO_read_filename(in,oidfile) <= 0)
			{
			BIO_printf(bio_err,"problems opening %s\n",oidfile);
			ERR_print_errors(bio_err);
			goto end;
			}
		OBJ_create_objects(in);
		}

	if (infile == NULL)
		BIO_set_fp(in,stdin,BIO_NOCLOSE);
	else
		{
		if (BIO_read_filename(in,infile) <= 0)
			{
			perror(infile);
			goto end;
			}
		}

	if (derfile) {
		if(!(derout = BIO_new_file(derfile, "wb"))) {
			BIO_printf(bio_err,"problems opening %s\n",derfile);
			ERR_print_errors(bio_err);
			goto end;
		}
	}

	if ((buf=BUF_MEM_new()) == NULL) goto end;
	if (!BUF_MEM_grow(buf,BUFSIZ*8)) goto end; /* Pre-allocate :-) */

	if (informat == FORMAT_PEM)
		{
		BIO *tmp;

		if ((b64=BIO_new(BIO_f_base64())) == NULL)
			goto end;
		BIO_push(b64,in);
		tmp=in;
		in=b64;
		b64=tmp;
		}

	num=0;
	for (;;)
		{
		if (!BUF_MEM_grow(buf,(int)num+BUFSIZ)) goto end;
		i=BIO_read(in,&(buf->data[num]),BUFSIZ);
		if (i <= 0) break;
		num+=i;
		}
	str=buf->data;

	/* If any structs to parse go through in sequence */

	if (sk_num(osk))
		{
		tmpbuf=(unsigned char *)str;
		tmplen=num;
		for (i=0; i<sk_num(osk); i++)
			{
			ASN1_TYPE *atmp;
			j=atoi(sk_value(osk,i));
			if (j == 0)
				{
				BIO_printf(bio_err,"'%s' is an invalid number\n",sk_value(osk,i));
				continue;
				}
			tmpbuf+=j;
			tmplen-=j;
			atmp = at;
			at = d2i_ASN1_TYPE(NULL,&tmpbuf,tmplen);
			ASN1_TYPE_free(atmp);
			if(!at)
				{
				BIO_printf(bio_err,"Error parsing structure\n");
				ERR_print_errors(bio_err);
				goto end;
				}
			/* hmm... this is a little evil but it works */
			tmpbuf=at->value.asn1_string->data;
			tmplen=at->value.asn1_string->length;
			}
		str=(char *)tmpbuf;
		num=tmplen;
		}

	if (length == 0) length=(unsigned int)num;
	if(derout) {
		if(BIO_write(derout, str + offset, length) != (int)length) {
			BIO_printf(bio_err, "Error writing output\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (!noout &&
	    !ASN1_parse_dump(out,(unsigned char *)&(str[offset]),length,
		    indent,dump))
		{
		ERR_print_errors(bio_err);
		goto end;
		}
	ret=0;
end:
	BIO_free(derout);
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	if (b64 != NULL) BIO_free(b64);
	if (ret != 0)
		ERR_print_errors(bio_err);
	if (buf != NULL) BUF_MEM_free(buf);
	if (at != NULL) ASN1_TYPE_free(at);
	if (osk != NULL) sk_free(osk);
	OBJ_cleanup();
	OPENSSL_EXIT(ret);
	}
Beispiel #4
0
TXT_DB *TXT_DB_read(BIO *in, int num)
{
    TXT_DB *ret = NULL;
    int er = 1;
    int esc = 0;
    long ln = 0;
    int i, add, n;
    int size = BUFSIZE;
    int offset = 0;
    char *p, **pp, *f;
    BUF_MEM *buf = NULL;

    if ((buf = BUF_MEM_new()) == NULL)
        goto err;
    if (!BUF_MEM_grow(buf, size))
        goto err;

    if ((ret = (TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL)
        goto err;
    ret->num_fields = num;
    ret->index = NULL;
    ret->qual = NULL;
    if ((ret->data = sk_new_null()) == NULL)
        goto err;
    if ((ret->index =
         (LHASH **)OPENSSL_malloc(sizeof(LHASH *) * num)) == NULL)
        goto err;
    if ((ret->qual =
         (int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **)) *
                                           num)) == NULL)
        goto err;
    for (i = 0; i < num; i++) {
        ret->index[i] = NULL;
        ret->qual[i] = NULL;
    }

    add = (num + 1) * sizeof(char *);
    buf->data[size - 1] = '\0';
    offset = 0;
    for (;;) {
        if (offset != 0) {
            size += BUFSIZE;
            if (!BUF_MEM_grow_clean(buf, size))
                goto err;
        }
        buf->data[offset] = '\0';
        BIO_gets(in, &(buf->data[offset]), size - offset);
        ln++;
        if (buf->data[offset] == '\0')
            break;
        if ((offset == 0) && (buf->data[0] == '#'))
            continue;
        i = strlen(&(buf->data[offset]));
        offset += i;
        if (buf->data[offset - 1] != '\n')
            continue;
        else {
            buf->data[offset - 1] = '\0'; /* blat the '\n' */
            if (!(p = (char *)OPENSSL_malloc(add + offset)))
                goto err;
            offset = 0;
        }
        pp = (char **)p;
        p += add;
        n = 0;
        pp[n++] = p;
        i = 0;
        f = buf->data;

        esc = 0;
        for (;;) {
            if (*f == '\0')
                break;
            if (*f == '\t') {
                if (esc)
                    p--;
                else {
                    *(p++) = '\0';
                    f++;
                    if (n >= num)
                        break;
                    pp[n++] = p;
                    continue;
                }
            }
            esc = (*f == '\\');
            *(p++) = *(f++);
        }
        *(p++) = '\0';
        if ((n != num) || (*f != '\0')) {
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty
                                                               * fix :-( */
            fprintf(stderr,
                    "wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",
                    ln, num, n, f);
#endif
            er = 2;
            goto err;
        }
        pp[n] = p;
        if (!sk_push(ret->data, (char *)pp)) {
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty
                                                               * fix :-( */
            fprintf(stderr, "failure in sk_push\n");
#endif
            er = 2;
            goto err;
        }
Beispiel #5
0
TokenError _backend_createRequest(const RegutilInfo *info,
                                  const char *hostname,
                                  const char *password,
                                  char **request, size_t *reqlen) {
    // OpenSSL seeds the PRNG automatically, see the manual page for RAND_add.
    if (!RAND_status()) {
        fprintf(stderr, BINNAME ": no random state!\n");
        return TokenError_NoRandomState;
    }
    
    // Abort if there are no requests
    *request = NULL;
    if (!info->pkcs10) return TokenError_Unknown;
    
    // Create certificate requests
    bool ok = true;
    CertReq *reqs = NULL;
    STACK *x509reqs = sk_new_null();
    for (const RegutilPKCS10 *pkcs10 = info->pkcs10; pkcs10 != NULL;
         pkcs10 = pkcs10->next) {
        
        RSA *rsa = NULL;
        EVP_PKEY *privkey = NULL;
        X509_NAME *subject = NULL;
        X509_REQ *x509req = NULL;
        STACK_OF(X509_EXTENSION) *exts = NULL;
        
        // Check the parameters.
        // Maximum key size in OpenSSL:
        // http://www.mail-archive.com/[email protected]/msg58229.html
        if (!pkcs10->subjectDN || pkcs10->keySize < 1024 ||
            pkcs10->keySize > 16384)
            goto req_error;
        
        // Generate key pair
        // FIXME deprecated function
        // TODO use OPENSSL_NO_DEPRECATED
        rsa = RSA_generate_key(pkcs10->keySize, RSA_F4, NULL, NULL);
        if (!rsa) goto req_error;
        privkey = EVP_PKEY_new();
        if (!privkey) goto req_error;
        EVP_PKEY_assign_RSA(privkey, rsa);
        
        // Subject name
        subject = certutil_parse_dn(pkcs10->subjectDN, pkcs10->includeFullDN);
        if (!subject) goto req_error;
        
        // Create request
        x509req = X509_REQ_new();
        if (!x509req ||
            !X509_REQ_set_version(x509req, 0) ||
            !X509_REQ_set_subject_name(x509req, subject) ||
            !X509_REQ_set_pubkey(x509req, privkey)) { // yes this is correct(!)
            
            certutil_updateErrorString();
            goto req_error;
        }
        
        // Set attributes
        exts = sk_X509_EXTENSION_new_null();
        if (!exts) goto req_error;
        
        X509_EXTENSION *ext = makeKeyUsageExt(pkcs10->keyUsage);
        if (!ext || !sk_X509_EXTENSION_push(exts, ext))
            goto req_error;
        
        if (!X509_REQ_add_extensions(x509req, exts)) {
            certutil_updateErrorString();
            goto req_error;
        }
        exts = NULL;
        
        // Add signature
        if (!X509_REQ_sign(x509req, privkey, EVP_sha1())) {
            certutil_updateErrorString();
            goto req_error;
        }
        
        // Store in list
        CertReq *req = malloc(sizeof(CertReq));
        req->pkcs10 = pkcs10;
        req->privkey = privkey;
        req->rsa = rsa;
        req->x509 = x509req;
        req->next = reqs;
        reqs = req;
        
        sk_push(x509reqs, (char*)x509req);
        
        continue;
        
      req_error:
        // Clean up and set error flag
        if (privkey) EVP_PKEY_free(privkey);
        else if (rsa) RSA_free(rsa);
        
        X509_NAME_free(subject);
        sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
        X509_REQ_free(x509req);
        
        ok = false;
    }
    
    TokenError error = TokenError_Unknown;
    
    if (ok) {
        // Determine filename from certificate name
        char *filename = certutil_makeFilename(X509_REQ_get_subject_name(reqs->x509));
        
        // Build the certificate request
        request_wrap(x509reqs, request, reqlen);
        
        if (*request && filename) {
            // Create the key file in ~/cbt/name.p12
            FILE *keyfile = platform_openLocked(filename, Platform_OpenCreate);
            if (!keyfile) {
                error = TokenError_CantCreateFile;
            } else {
                error = saveKeys(reqs, hostname, password, keyfile);
                if (!platform_closeLocked(keyfile) && !error)
                    error = TokenError_CantCreateFile;
            }
            
        }
        
        if (filename) free(filename);
        if (error && *request) free(*request);
    }
    
    // Free reqs
    while (reqs) {
        RSA_free(reqs->rsa); // This free's privkey too
        X509_REQ_free(reqs->x509);
        
        CertReq *next = reqs->next;
        free(reqs);
        reqs = next;
    }
    sk_free(x509reqs);
    
    return error;
}
Beispiel #6
0
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    char *infile=NULL, *outfile=NULL, *keyname = NULL;	
    char *certfile=NULL;
    BIO *in=NULL, *out = NULL;
    char **args;
    char *name = NULL;
    char *csp_name = NULL;
    PKCS12 *p12 = NULL;
    char pass[50], macpass[50];
    int export_cert = 0;
    int options = 0;
    int chain = 0;
    int badarg = 0;
    int iter = PKCS12_DEFAULT_ITER;
    int maciter = PKCS12_DEFAULT_ITER;
    int twopass = 0;
    int keytype = 0;
    int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
    int ret = 1;
    int macver = 1;
    int noprompt = 0;
    STACK *canames = NULL;
    char *cpass = NULL, *mpass = NULL;
    char *passargin = NULL, *passargout = NULL, *passarg = NULL;
    char *passin = NULL, *passout = NULL;
    char *inrand = NULL;
    char *CApath = NULL, *CAfile = NULL;
    char *engine=NULL;

    apps_startup();

    enc = EVP_des_ede3_cbc();
    if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;

    args = argv + 1;


    while (*args) {
	if (*args[0] == '-') {
		if (!strcmp (*args, "-nokeys")) options |= NOKEYS;
		else if (!strcmp (*args, "-keyex")) keytype = KEY_EX;
		else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG;
		else if (!strcmp (*args, "-nocerts")) options |= NOCERTS;
		else if (!strcmp (*args, "-clcerts")) options |= CLCERTS;
		else if (!strcmp (*args, "-cacerts")) options |= CACERTS;
		else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS);
		else if (!strcmp (*args, "-info")) options |= INFO;
		else if (!strcmp (*args, "-chain")) chain = 1;
		else if (!strcmp (*args, "-twopass")) twopass = 1;
		else if (!strcmp (*args, "-nomacver")) macver = 0;
		else if (!strcmp (*args, "-descert"))
    			cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
		else if (!strcmp (*args, "-export")) export_cert = 1;
		else if (!strcmp (*args, "-des")) enc=EVP_des_cbc();
#ifndef OPENSSL_NO_IDEA
		else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc();
#endif
		else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc();
		else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc();
		else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc();
#endif
		else if (!strcmp (*args, "-noiter")) iter = 1;
		else if (!strcmp (*args, "-maciter"))
					 maciter = PKCS12_DEFAULT_ITER;
		else if (!strcmp (*args, "-nomaciter"))
					 maciter = 1;
		else if (!strcmp (*args, "-nodes")) enc=NULL;
		else if (!strcmp (*args, "-certpbe")) {
			if (args[1]) {
				args++;
				cert_pbe=OBJ_txt2nid(*args);
				if(cert_pbe == NID_undef) {
					BIO_printf(bio_err,
						 "Unknown PBE algorithm %s\n", *args);
					badarg = 1;
				}
			} else badarg = 1;
		} else if (!strcmp (*args, "-keypbe")) {
			if (args[1]) {
				args++;
				key_pbe=OBJ_txt2nid(*args);
				if(key_pbe == NID_undef) {
					BIO_printf(bio_err,
						 "Unknown PBE algorithm %s\n", *args);
					badarg = 1;
				}
			} else badarg = 1;
		} else if (!strcmp (*args, "-rand")) {
		    if (args[1]) {
			args++;	
			inrand = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-inkey")) {
		    if (args[1]) {
			args++;	
			keyname = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-certfile")) {
		    if (args[1]) {
			args++;	
			certfile = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-name")) {
		    if (args[1]) {
			args++;	
			name = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-CSP")) {
		    if (args[1]) {
			args++;	
			csp_name = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-caname")) {
		    if (args[1]) {
			args++;	
			if (!canames) canames = sk_new_null();
			sk_push(canames, *args);
		    } else badarg = 1;
		} else if (!strcmp (*args, "-in")) {
		    if (args[1]) {
			args++;	
			infile = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-out")) {
		    if (args[1]) {
			args++;	
			outfile = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-passin")) {
		    if (args[1]) {
			args++;	
			passargin = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-passout")) {
		    if (args[1]) {
			args++;	
			passargout = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-password")) {
		    if (args[1]) {
			args++;	
			passarg = *args;
		    	noprompt = 1;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-CApath")) {
		    if (args[1]) {
			args++;	
			CApath = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-CAfile")) {
		    if (args[1]) {
			args++;	
			CAfile = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-engine")) {
		    if (args[1]) {
			args++;	
			engine = *args;
		    } else badarg = 1;
		} else badarg = 1;

	} else badarg = 1;
	args++;
    }

    if (badarg) {
	BIO_printf (bio_err, "Usage: pkcs12 [options]\n");
	BIO_printf (bio_err, "where options are\n");
	BIO_printf (bio_err, "-export       output PKCS12 file\n");
	BIO_printf (bio_err, "-chain        add certificate chain\n");
	BIO_printf (bio_err, "-inkey file   private key if not infile\n");
	BIO_printf (bio_err, "-certfile f   add all certs in f\n");
	BIO_printf (bio_err, "-CApath arg   - PEM format directory of CA's\n");
	BIO_printf (bio_err, "-CAfile arg   - PEM format file of CA's\n");
	BIO_printf (bio_err, "-name \"name\"  use name as friendly name\n");
	BIO_printf (bio_err, "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
	BIO_printf (bio_err, "-in  infile   input filename\n");
	BIO_printf (bio_err, "-out outfile  output filename\n");
	BIO_printf (bio_err, "-noout        don't output anything, just verify.\n");
	BIO_printf (bio_err, "-nomacver     don't verify MAC.\n");
	BIO_printf (bio_err, "-nocerts      don't output certificates.\n");
	BIO_printf (bio_err, "-clcerts      only output client certificates.\n");
	BIO_printf (bio_err, "-cacerts      only output CA certificates.\n");
	BIO_printf (bio_err, "-nokeys       don't output private keys.\n");
	BIO_printf (bio_err, "-info         give info about PKCS#12 structure.\n");
	BIO_printf (bio_err, "-des          encrypt private keys with DES\n");
	BIO_printf (bio_err, "-des3         encrypt private keys with triple DES (default)\n");
#ifndef OPENSSL_NO_IDEA
	BIO_printf (bio_err, "-idea         encrypt private keys with idea\n");
#endif
#ifndef OPENSSL_NO_AES
	BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
	BIO_printf (bio_err, "              encrypt PEM output with cbc aes\n");
#endif
	BIO_printf (bio_err, "-nodes        don't encrypt private keys\n");
	BIO_printf (bio_err, "-noiter       don't use encryption iteration\n");
	BIO_printf (bio_err, "-maciter      use MAC iteration\n");
	BIO_printf (bio_err, "-twopass      separate MAC, encryption passwords\n");
	BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
	BIO_printf (bio_err, "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
	BIO_printf (bio_err, "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
	BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
	BIO_printf (bio_err, "-keysig       set MS key signature type\n");
	BIO_printf (bio_err, "-password p   set import/export password source\n");
	BIO_printf (bio_err, "-passin p     input file pass phrase source\n");
	BIO_printf (bio_err, "-passout p    output file pass phrase source\n");
	BIO_printf (bio_err, "-engine e     use engine e, possibly a hardware device.\n");
	BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
	BIO_printf(bio_err,  "              load the file (or the files in the directory) into\n");
	BIO_printf(bio_err,  "              the random number generator\n");
    	goto end;
    }

    e = setup_engine(bio_err, engine, 0);

    if(passarg) {
	if(export_cert) passargout = passarg;
	else passargin = passarg;
    }

    if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
	BIO_printf(bio_err, "Error getting passwords\n");
	goto end;
    }

    if(!cpass) {
    	if(export_cert) cpass = passout;
    	else cpass = passin;
    }

    if(cpass) {
	mpass = cpass;
	noprompt = 1;
    } else {
	cpass = pass;
	mpass = macpass;
    }

    if(export_cert || inrand) {
    	app_RAND_load_file(NULL, bio_err, (inrand != NULL));
        if (inrand != NULL)
		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
			app_RAND_load_files(inrand));
    }
    ERR_load_crypto_strings();

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read files");
#endif

    if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE);
    else in = BIO_new_file(infile, "rb");
    if (!in) {
	    BIO_printf(bio_err, "Error opening input file %s\n",
						infile ? infile : "<stdin>");
	    perror (infile);
	    goto end;
   }

#if 0
   if (certfile) {
    	if(!(certsin = BIO_new_file(certfile, "r"))) {
	    BIO_printf(bio_err, "Can't open certificate file %s\n", certfile);
	    perror (certfile);
	    goto end;
	}
    }

    if (keyname) {
    	if(!(inkey = BIO_new_file(keyname, "r"))) {
	    BIO_printf(bio_err, "Can't key certificate file %s\n", keyname);
	    perror (keyname);
	    goto end;
	}
     }
#endif

#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
    CRYPTO_push_info("write files");
#endif

    if (!outfile) {
	out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	    out = BIO_push(tmpbio, out);
	}
#endif
    } else out = BIO_new_file(outfile, "wb");
    if (!out) {
	BIO_printf(bio_err, "Error opening output file %s\n",
						outfile ? outfile : "<stdout>");
	perror (outfile);
	goto end;
    }
    if (twopass) {
#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read MAC password");
#endif
	if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n");
    	    goto end;
       	}
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    }

    if (export_cert) {
	EVP_PKEY *key = NULL;
	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
	STACK_OF(PKCS7) *safes = NULL;
	PKCS12_SAFEBAG *bag = NULL;
	PKCS8_PRIV_KEY_INFO *p8 = NULL;
	PKCS7 *authsafe = NULL;
	X509 *ucert = NULL;
	STACK_OF(X509) *certs=NULL;
	char *catmp = NULL;
	int i;
	unsigned char keyid[EVP_MAX_MD_SIZE];
	unsigned int keyidlen = 0;

#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("process -export_cert");
	CRYPTO_push_info("reading private key");
#endif
	key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1,
		passin, e, "private key");
	if (!key) {
		goto export_end;
	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from input");
#endif

	/* Load in all certs in input file */
	if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
		"certificates"))) {
		goto export_end;
	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from input 2");
#endif

	for(i = 0; i < sk_X509_num(certs); i++) {
		ucert = sk_X509_value(certs, i);
		if(X509_check_private_key(ucert, key)) {
			X509_digest(ucert, EVP_sha1(), keyid, &keyidlen);
			break;
		}
	}
	if(!keyidlen) {
		ucert = NULL;
		BIO_printf(bio_err, "No certificate matches private key\n");
		goto export_end;
	}
	
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from certfile");
#endif

	bags = sk_PKCS12_SAFEBAG_new_null ();

	/* Add any more certificates asked for */
	if (certfile) {
		STACK_OF(X509) *morecerts=NULL;
		if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
					    NULL, e,
					    "certificates from certfile"))) {
			goto export_end;
		}
		while(sk_X509_num(morecerts) > 0) {
			sk_X509_push(certs, sk_X509_shift(morecerts));
		}
		sk_X509_free(morecerts);
 	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building chain");
#endif

	/* If chaining get chain from user cert */
	if (chain) {
        	int vret;
		STACK_OF(X509) *chain2;
		X509_STORE *store = X509_STORE_new();
		if (!store)
			{
			BIO_printf (bio_err, "Memory allocation error\n");
			goto export_end;
			}
		if (!X509_STORE_load_locations(store, CAfile, CApath))
			X509_STORE_set_default_paths (store);

		vret = get_cert_chain (ucert, store, &chain2);
		X509_STORE_free(store);

		if (!vret) {
		    /* Exclude verified certificate */
		    for (i = 1; i < sk_X509_num (chain2) ; i++) 
			sk_X509_push(certs, sk_X509_value (chain2, i));
		    /* Free first certificate */
		    X509_free(sk_X509_value(chain2, 0));
		    sk_X509_free(chain2);
		} else {
			BIO_printf (bio_err, "Error %s getting chain.\n",
					X509_verify_cert_error_string(vret));
			goto export_end;
		}			
    	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building bags");
#endif

	/* We now have loads of certificates: include them all */
	for(i = 0; i < sk_X509_num(certs); i++) {
		X509 *cert = NULL;
		cert = sk_X509_value(certs, i);
		bag = PKCS12_x5092certbag(cert);
		/* If it matches private key set id */
		if(cert == ucert) {
			if(name) PKCS12_add_friendlyname(bag, name, -1);
			PKCS12_add_localkeyid(bag, keyid, keyidlen);
		} else if((catmp = sk_shift(canames))) 
				PKCS12_add_friendlyname(bag, catmp, -1);
		sk_PKCS12_SAFEBAG_push(bags, bag);
	}
	sk_X509_pop_free(certs, X509_free);
	certs = NULL;

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("encrypting bags");
#endif

	if(!noprompt &&
		EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n");
	    goto export_end;
        }
	if (!twopass) strcpy(macpass, pass);
	/* Turn certbags into encrypted authsafe */
	authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0,
								 iter, bags);
	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	bags = NULL;

	if (!authsafe) {
		ERR_print_errors (bio_err);
		goto export_end;
	}

	safes = sk_PKCS7_new_null ();
	sk_PKCS7_push (safes, authsafe);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building shrouded key bag");
#endif

	/* Make a shrouded key bag */
	p8 = EVP_PKEY2PKCS8 (key);
	if(keytype) PKCS8_add_keyusage(p8, keytype);
	bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8);
	PKCS8_PRIV_KEY_INFO_free(p8);
	p8 = NULL;
        if (name) PKCS12_add_friendlyname (bag, name, -1);
	if(csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1);
	PKCS12_add_localkeyid (bag, keyid, keyidlen);
	bags = sk_PKCS12_SAFEBAG_new_null();
	sk_PKCS12_SAFEBAG_push (bags, bag);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("encrypting shrouded key bag");
#endif

	/* Turn it into unencrypted safe bag */
	authsafe = PKCS12_pack_p7data (bags);
	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	bags = NULL;
	sk_PKCS7_push (safes, authsafe);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building pkcs12");
#endif

	p12 = PKCS12_init(NID_pkcs7_data);

	PKCS12_pack_authsafes(p12, safes);

	sk_PKCS7_pop_free(safes, PKCS7_free);
	safes = NULL;

	PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("writing pkcs12");
#endif

	i2d_PKCS12_bio (out, p12);

	ret = 0;

    export_end:
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_pop_info();
	CRYPTO_push_info("process -export_cert: freeing");
#endif

	if (key) EVP_PKEY_free(key);
	if (certs) sk_X509_pop_free(certs, X509_free);
	if (safes) sk_PKCS7_pop_free(safes, PKCS7_free);
	if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif
	goto end;
	
    }

    if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
	ERR_print_errors(bio_err);
	goto end;
    }

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read import password");
#endif
    if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n");
	goto end;
    }
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif

    if (!twopass) strcpy(macpass, pass);

    if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
    if(macver) {
#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("verify MAC");
#endif
	/* If we enter empty password try no password first */
	if(!macpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
		/* If mac and crypto pass the same set it to NULL too */
		if(!twopass) cpass = NULL;
	} else if (!PKCS12_verify_mac(p12, mpass, -1)) {
	    BIO_printf (bio_err, "Mac verify error: invalid password?\n");
	    ERR_print_errors (bio_err);
	    goto end;
	}
	BIO_printf (bio_err, "MAC verified OK\n");
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    }

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("output keys and certificates");
#endif
    if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) {
	BIO_printf(bio_err, "Error outputting keys and certificates\n");
	ERR_print_errors (bio_err);
	goto end;
    }
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    ret = 0;
 end:
    if (p12) PKCS12_free(p12);
    if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
#ifdef CRYPTO_MDEBUG
    CRYPTO_remove_all_info();
#endif
    BIO_free(in);
    BIO_free_all(out);
    if (canames) sk_free(canames);
    if(passin) OPENSSL_free(passin);
    if(passout) OPENSSL_free(passout);
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Beispiel #7
0
STACK *d2i_ASN1_SET(STACK **a, const unsigned char **pp, long length,
		    d2i_of_void *d2i, void (*free_func)(void *), int ex_tag,
		    int ex_class)
	{
	ASN1_const_CTX c;
	STACK *ret=NULL;

	if ((a == NULL) || ((*a) == NULL))
		{
		if ((ret=sk_new_null()) == NULL)
			{
			ASN1err(ASN1_F_D2I_ASN1_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		}
	else
		ret=(*a);

	c.p= *pp;
	c.max=(length == 0)?0:(c.p+length);

	c.inf=ASN1_get_object(&c.p,&c.slen,&c.tag,&c.xclass,(long)(c.max-c.p));
	if (c.inf & 0x80) goto err;
	if (ex_class != c.xclass)
		{
		ASN1err(ASN1_F_D2I_ASN1_SET,ASN1_R_BAD_CLASS);
		goto err;
		}
	if (ex_tag != c.tag)
		{
		ASN1err(ASN1_F_D2I_ASN1_SET,ASN1_R_BAD_TAG);
		goto err;
		}
	if ((c.slen+c.p) > c.max)
		{
		ASN1err(ASN1_F_D2I_ASN1_SET,ASN1_R_LENGTH_ERROR);
		goto err;
		}
	/* check for infinite constructed - it can be as long
	 * as the amount of data passed to us */
	if (c.inf == (V_ASN1_CONSTRUCTED+1))
		c.slen=(long)(length+ *pp-c.p);
	c.max=c.p+c.slen;

	while (c.p < c.max)
		{
		char *s;

		if (M_ASN1_D2I_end_sequence()) break;
		/* XXX: This was called with 4 arguments, incorrectly, it seems
		   if ((s=func(NULL,&c.p,c.slen,c.max-c.p)) == NULL) */
		if ((s=d2i(NULL,&c.p,c.slen)) == NULL)
			{
			ASN1err(ASN1_F_D2I_ASN1_SET,ASN1_R_ERROR_PARSING_SET_ELEMENT);
			asn1_add_error(*pp,(int)(c.q- *pp));
			goto err;
			}
		if (!sk_push(ret,s)) goto err;
		}
	if (a != NULL) (*a)=ret;
	*pp=c.p;
	return(ret);
err:
	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
		{
		if (free_func != NULL)
			sk_pop_free(ret,free_func);
		else
			sk_free(ret);
		}
	return(NULL);
	}
int MAIN(int argc, char **argv)
	{
	int ret=1,i;
	const char **pp;
	int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0;
	ENGINE *e;
	STACK *engines = sk_new_null();
	STACK *pre_cmds = sk_new_null();
	STACK *post_cmds = sk_new_null();
	int badops=1;
	BIO *bio_out=NULL;
	const char *indent = "     ";

	apps_startup();
	SSL_load_error_strings();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;
	bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	bio_out = BIO_push(tmpbio, bio_out);
	}
#endif

	argc--;
	argv++;
	while (argc >= 1)
		{
		if (strncmp(*argv,"-v",2) == 0)
			{
			if(strspn(*argv + 1, "v") < strlen(*argv + 1))
				goto skip_arg_loop;
			if((verbose=strlen(*argv + 1)) > 4)
				goto skip_arg_loop;
			}
		else if (strcmp(*argv,"-c") == 0)
			list_cap=1;
		else if (strncmp(*argv,"-t",2) == 0)
			{
			test_avail=1;
			if(strspn(*argv + 1, "t") < strlen(*argv + 1))
				goto skip_arg_loop;
			if((test_avail_noise = strlen(*argv + 1) - 1) > 1)
				goto skip_arg_loop;
			}
		else if (strcmp(*argv,"-pre") == 0)
			{
			argc--; argv++;
			if (argc == 0)
				goto skip_arg_loop;
			sk_push(pre_cmds,*argv);
			}
		else if (strcmp(*argv,"-post") == 0)
			{
			argc--; argv++;
			if (argc == 0)
				goto skip_arg_loop;
			sk_push(post_cmds,*argv);
			}
		else if ((strncmp(*argv,"-h",2) == 0) ||
				(strcmp(*argv,"-?") == 0))
			goto skip_arg_loop;
		else
			sk_push(engines,*argv);
		argc--;
		argv++;
		}
	/* Looks like everything went OK */
	badops = 0;
skip_arg_loop:

	if (badops)
		{
		for (pp=engine_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,"%s",*pp);
		goto end;
		}

	if (sk_num(engines) == 0)
		{
		for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e))
			{
			sk_push(engines,(char *)ENGINE_get_id(e));
			}
		}

	for (i=0; i<sk_num(engines); i++)
		{
		const char *id = sk_value(engines,i);
		if ((e = ENGINE_by_id(id)) != NULL)
			{
			const char *name = ENGINE_get_name(e);
			/* Do "id" first, then "name". Easier to auto-parse. */
			BIO_printf(bio_out, "(%s) %s\n", id, name);
			util_do_cmds(e, pre_cmds, bio_out, indent);
			if (strcmp(ENGINE_get_id(e), id) != 0)
				{
				BIO_printf(bio_out, "Loaded: (%s) %s\n",
					ENGINE_get_id(e), ENGINE_get_name(e));
				}
			if (list_cap)
				{
				int cap_size = 256;
				char *cap_buf = NULL;
				int k,n;
				const int *nids;
				ENGINE_CIPHERS_PTR fn_c;
				ENGINE_DIGESTS_PTR fn_d;

				if (ENGINE_get_RSA(e) != NULL
					&& !append_buf(&cap_buf, "RSA",
						&cap_size, 256))
					goto end;
				if (ENGINE_get_DSA(e) != NULL
					&& !append_buf(&cap_buf, "DSA",
						&cap_size, 256))
					goto end;
				if (ENGINE_get_DH(e) != NULL
					&& !append_buf(&cap_buf, "DH",
						&cap_size, 256))
					goto end;
				if (ENGINE_get_RAND(e) != NULL
					&& !append_buf(&cap_buf, "RAND",
						&cap_size, 256))
					goto end;

				fn_c = ENGINE_get_ciphers(e);
				if(!fn_c) goto skip_ciphers;
				n = fn_c(e, NULL, &nids, 0);
				for(k=0 ; k < n ; ++k)
					if(!append_buf(&cap_buf,
						       OBJ_nid2sn(nids[k]),
						       &cap_size, 256))
						goto end;

skip_ciphers:
				fn_d = ENGINE_get_digests(e);
				if(!fn_d) goto skip_digests;
				n = fn_d(e, NULL, &nids, 0);
				for(k=0 ; k < n ; ++k)
					if(!append_buf(&cap_buf,
						       OBJ_nid2sn(nids[k]),
						       &cap_size, 256))
						goto end;

skip_digests:
				if (cap_buf && (*cap_buf != '\0'))
					BIO_printf(bio_out, " [%s]\n", cap_buf);

				OPENSSL_free(cap_buf);
				}
			if(test_avail)
				{
				BIO_printf(bio_out, "%s", indent);
				if (ENGINE_init(e))
					{
					BIO_printf(bio_out, "[ available ]\n");
					util_do_cmds(e, post_cmds, bio_out, indent);
					ENGINE_finish(e);
					}
				else
					{
					BIO_printf(bio_out, "[ unavailable ]\n");
					if(test_avail_noise)
						ERR_print_errors_fp(stdout);
					ERR_clear_error();
					}
				}
			if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
				goto end;
			ENGINE_free(e);
			}
		else
			ERR_print_errors(bio_err);
		}

	ret=0;
end:

	ERR_print_errors(bio_err);
	sk_pop_free(engines, identity);
	sk_pop_free(pre_cmds, identity);
	sk_pop_free(post_cmds, identity);
	if (bio_out != NULL) BIO_free_all(bio_out);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent)
	{
	static const int line_wrap = 78;
	int num;
	int ret = 0;
	char *name = NULL;
	char *desc = NULL;
	int flags;
	int xpos = 0;
	STACK *cmds = NULL;
	if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
			((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
					0, NULL, NULL)) <= 0))
		{
#if 0
		BIO_printf(bio_out, "%s<no control commands>\n", indent);
#endif
		return 1;
		}

	cmds = sk_new_null();

	if(!cmds)
		goto err;
	do {
		int len;
		/* Get the command input flags */
		if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
					NULL, NULL)) < 0)
			goto err;
                if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4)
                        {
                        /* Get the command name */
                        if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
                                NULL, NULL)) <= 0)
                                goto err;
                        if((name = OPENSSL_malloc(len + 1)) == NULL)
                                goto err;
                        if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
                                NULL) <= 0)
                                goto err;
                        /* Get the command description */
                        if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
                                NULL, NULL)) < 0)
                                goto err;
                        if(len > 0)
                                {
                                if((desc = OPENSSL_malloc(len + 1)) == NULL)
                                        goto err;
                                if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
                                        NULL) <= 0)
                                        goto err;
                                }
                        /* Now decide on the output */
                        if(xpos == 0)
                                /* Do an indent */
                                xpos = BIO_printf(bio_out, indent);
                        else
                                /* Otherwise prepend a ", " */
                                xpos += BIO_printf(bio_out, ", ");
                        if(verbose == 1)
                                {
                                /* We're just listing names, comma-delimited */
                                if((xpos > (int)strlen(indent)) &&
					(xpos + (int)strlen(name) > line_wrap))
                                        {
                                        BIO_printf(bio_out, "\n");
                                        xpos = BIO_printf(bio_out, indent);
                                        }
                                xpos += BIO_printf(bio_out, "%s", name);
                                }
                        else
                                {
                                /* We're listing names plus descriptions */
                                BIO_printf(bio_out, "%s: %s\n", name,
                                        (desc == NULL) ? "<no description>" : desc);
                                /* ... and sometimes input flags */
                                if((verbose >= 3) && !util_flags(bio_out, flags,
                                        indent))
                                        goto err;
                                xpos = 0;
                                }
                        }
		OPENSSL_free(name); name = NULL;
		if(desc) { OPENSSL_free(desc); desc = NULL; }
		/* Move to the next command */
		num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE,
					num, NULL, NULL);
		} while(num > 0);
	if(xpos > 0)
		BIO_printf(bio_out, "\n");
	ret = 1;
err:
	if(cmds) sk_pop_free(cmds, identity);
	if(name) OPENSSL_free(name);
	if(desc) OPENSSL_free(desc);
	return ret;
	}
Beispiel #10
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	char **args;
	char *host = NULL, *port = NULL, *path = "/";
	char *reqin = NULL, *respin = NULL;
	char *reqout = NULL, *respout = NULL;
	char *signfile = NULL, *keyfile = NULL;
	char *rsignfile = NULL, *rkeyfile = NULL;
	char *outfile = NULL;
	int add_nonce = 1, noverify = 0, use_ssl = -1;
	OCSP_REQUEST *req = NULL;
	OCSP_RESPONSE *resp = NULL;
	OCSP_BASICRESP *bs = NULL;
	X509 *issuer = NULL, *cert = NULL;
	X509 *signer = NULL, *rsigner = NULL;
	EVP_PKEY *key = NULL, *rkey = NULL;
	BIO *acbio = NULL, *cbio = NULL;
	BIO *derbio = NULL;
	BIO *out = NULL;
	int req_text = 0, resp_text = 0;
	long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
	char *CAfile = NULL, *CApath = NULL;
	X509_STORE *store = NULL;
	SSL_CTX *ctx = NULL;
	STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
	char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
	unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
	int ret = 1;
	int accept_count = -1;
	int badarg = 0;
	int i;
	int ignore_err = 0;
	STACK *reqnames = NULL;
	STACK_OF(OCSP_CERTID) *ids = NULL;

	X509 *rca_cert = NULL;
	char *ridx_filename = NULL;
	char *rca_filename = NULL;
	CA_DB *rdb = NULL;
	int nmin = 0, ndays = -1;

	if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;
	SSL_load_error_strings();
	OpenSSL_add_ssl_algorithms();
	args = argv + 1;
	reqnames = sk_new_null();
	ids = sk_OCSP_CERTID_new_null();
	while (!badarg && *args && *args[0] == '-')
		{
		if (!strcmp(*args, "-out"))
			{
			if (args[1])
				{
				args++;
				outfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-url"))
			{
			if (args[1])
				{
				args++;
				if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl))
					{
					BIO_printf(bio_err, "Error parsing URL\n");
					badarg = 1;
					}
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-host"))
			{
			if (args[1])
				{
				args++;
				host = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-port"))
			{
			if (args[1])
				{
				args++;
				port = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-ignore_err"))
			ignore_err = 1;
		else if (!strcmp(*args, "-noverify"))
			noverify = 1;
		else if (!strcmp(*args, "-nonce"))
			add_nonce = 2;
		else if (!strcmp(*args, "-no_nonce"))
			add_nonce = 0;
		else if (!strcmp(*args, "-resp_no_certs"))
			rflags |= OCSP_NOCERTS;
		else if (!strcmp(*args, "-resp_key_id"))
			rflags |= OCSP_RESPID_KEY;
		else if (!strcmp(*args, "-no_certs"))
			sign_flags |= OCSP_NOCERTS;
		else if (!strcmp(*args, "-no_signature_verify"))
			verify_flags |= OCSP_NOSIGS;
		else if (!strcmp(*args, "-no_cert_verify"))
			verify_flags |= OCSP_NOVERIFY;
		else if (!strcmp(*args, "-no_chain"))
			verify_flags |= OCSP_NOCHAIN;
		else if (!strcmp(*args, "-no_cert_checks"))
			verify_flags |= OCSP_NOCHECKS;
		else if (!strcmp(*args, "-no_explicit"))
			verify_flags |= OCSP_NOEXPLICIT;
		else if (!strcmp(*args, "-trust_other"))
			verify_flags |= OCSP_TRUSTOTHER;
		else if (!strcmp(*args, "-no_intern"))
			verify_flags |= OCSP_NOINTERN;
		else if (!strcmp(*args, "-text"))
			{
			req_text = 1;
			resp_text = 1;
			}
		else if (!strcmp(*args, "-req_text"))
			req_text = 1;
		else if (!strcmp(*args, "-resp_text"))
			resp_text = 1;
		else if (!strcmp(*args, "-reqin"))
			{
			if (args[1])
				{
				args++;
				reqin = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-respin"))
			{
			if (args[1])
				{
				args++;
				respin = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-signer"))
			{
			if (args[1])
				{
				args++;
				signfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-VAfile"))
			{
			if (args[1])
				{
				args++;
				verify_certfile = *args;
				verify_flags |= OCSP_TRUSTOTHER;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-sign_other"))
			{
			if (args[1])
				{
				args++;
				sign_certfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-verify_other"))
			{
			if (args[1])
				{
				args++;
				verify_certfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-CAfile"))
			{
			if (args[1])
				{
				args++;
				CAfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-CApath"))
			{
			if (args[1])
				{
				args++;
				CApath = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-validity_period"))
			{
			if (args[1])
				{
				args++;
				nsec = atol(*args);
				if (nsec < 0)
					{
					BIO_printf(bio_err,
						"Illegal validity period %s\n",
						*args);
					badarg = 1;
					}
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-status_age"))
			{
			if (args[1])
				{
				args++;
				maxage = atol(*args);
				if (maxage < 0)
					{
					BIO_printf(bio_err,
						"Illegal validity age %s\n",
						*args);
					badarg = 1;
					}
				}
			else badarg = 1;
			}
		 else if (!strcmp(*args, "-signkey"))
			{
			if (args[1])
				{
				args++;
				keyfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-reqout"))
			{
			if (args[1])
				{
				args++;
				reqout = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-respout"))
			{
			if (args[1])
				{
				args++;
				respout = *args;
				}
			else badarg = 1;
			}
		 else if (!strcmp(*args, "-path"))
			{
			if (args[1])
				{
				args++;
				path = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-issuer"))
			{
			if (args[1])
				{
				args++;
				X509_free(issuer);
				issuer = load_cert(bio_err, *args, FORMAT_PEM,
					NULL, e, "issuer certificate");
				if(!issuer) goto end;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-cert"))
			{
			if (args[1])
				{
				args++;
				X509_free(cert);
				cert = load_cert(bio_err, *args, FORMAT_PEM,
					NULL, e, "certificate");
				if(!cert) goto end;
				if(!add_ocsp_cert(&req, cert, issuer, ids))
					goto end;
				if(!sk_push(reqnames, *args))
					goto end;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-serial"))
			{
			if (args[1])
				{
				args++;
				if(!add_ocsp_serial(&req, *args, issuer, ids))
					goto end;
				if(!sk_push(reqnames, *args))
					goto end;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-index"))
			{
			if (args[1])
				{
				args++;
				ridx_filename = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-CA"))
			{
			if (args[1])
				{
				args++;
				rca_filename = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-nmin"))
			{
			if (args[1])
				{
				args++;
				nmin = atol(*args);
				if (nmin < 0)
					{
					BIO_printf(bio_err,
						"Illegal update period %s\n",
						*args);
					badarg = 1;
					}
				}
				if (ndays == -1)
					ndays = 0;
			else badarg = 1;
			}
		else if (!strcmp (*args, "-nrequest"))
			{
			if (args[1])
				{
				args++;
				accept_count = atol(*args);
				if (accept_count < 0)
					{
					BIO_printf(bio_err,
						"Illegal accept count %s\n",
						*args);
					badarg = 1;
					}
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-ndays"))
			{
			if (args[1])
				{
				args++;
				ndays = atol(*args);
				if (ndays < 0)
					{
					BIO_printf(bio_err,
						"Illegal update period %s\n",
						*args);
					badarg = 1;
					}
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-rsigner"))
			{
			if (args[1])
				{
				args++;
				rsignfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-rkey"))
			{
			if (args[1])
				{
				args++;
				rkeyfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-rother"))
			{
			if (args[1])
				{
				args++;
				rcertfile = *args;
				}
			else badarg = 1;
			}
		else badarg = 1;
		args++;
		}

	/* Have we anything to do? */
	if (!req && !reqin && !respin && !(port && ridx_filename)) badarg = 1;

	if (badarg)
		{
		BIO_printf (bio_err, "OCSP utility\n");
		BIO_printf (bio_err, "Usage ocsp [options]\n");
		BIO_printf (bio_err, "where options are\n");
		BIO_printf (bio_err, "-out file          output filename\n");
		BIO_printf (bio_err, "-issuer file       issuer certificate\n");
		BIO_printf (bio_err, "-cert file         certificate to check\n");
		BIO_printf (bio_err, "-serial n          serial number to check\n");
		BIO_printf (bio_err, "-signer file       certificate to sign OCSP request with\n");
		BIO_printf (bio_err, "-signkey file      private key to sign OCSP request with\n");
		BIO_printf (bio_err, "-sign_other file   additional certificates to include in signed request\n");
		BIO_printf (bio_err, "-no_certs          don't include any certificates in signed request\n");
		BIO_printf (bio_err, "-req_text          print text form of request\n");
		BIO_printf (bio_err, "-resp_text         print text form of response\n");
		BIO_printf (bio_err, "-text              print text form of request and response\n");
		BIO_printf (bio_err, "-reqout file       write DER encoded OCSP request to \"file\"\n");
		BIO_printf (bio_err, "-respout file      write DER encoded OCSP reponse to \"file\"\n");
		BIO_printf (bio_err, "-reqin file        read DER encoded OCSP request from \"file\"\n");
		BIO_printf (bio_err, "-respin file       read DER encoded OCSP reponse from \"file\"\n");
		BIO_printf (bio_err, "-nonce             add OCSP nonce to request\n");
		BIO_printf (bio_err, "-no_nonce          don't add OCSP nonce to request\n");
		BIO_printf (bio_err, "-url URL           OCSP responder URL\n");
		BIO_printf (bio_err, "-host host:n       send OCSP request to host on port n\n");
		BIO_printf (bio_err, "-path              path to use in OCSP request\n");
		BIO_printf (bio_err, "-CApath dir        trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file       trusted certificates file\n");
		BIO_printf (bio_err, "-VAfile file       validator certificates file\n");
		BIO_printf (bio_err, "-validity_period n maximum validity discrepancy in seconds\n");
		BIO_printf (bio_err, "-status_age n      maximum status age in seconds\n");
		BIO_printf (bio_err, "-noverify          don't verify response at all\n");
		BIO_printf (bio_err, "-verify_other file additional certificates to search for signer\n");
		BIO_printf (bio_err, "-trust_other       don't verify additional certificates\n");
		BIO_printf (bio_err, "-no_intern         don't search certificates contained in response for signer\n");
		BIO_printf (bio_err, "-no_signature_verify don't check signature on response\n");
		BIO_printf (bio_err, "-no_cert_verify    don't check signing certificate\n");
		BIO_printf (bio_err, "-no_chain          don't chain verify response\n");
		BIO_printf (bio_err, "-no_cert_checks    don't do additional checks on signing certificate\n");
		BIO_printf (bio_err, "-port num		 port to run responder on\n");
		BIO_printf (bio_err, "-index file	 certificate status index file\n");
		BIO_printf (bio_err, "-CA file		 CA certificate\n");
		BIO_printf (bio_err, "-rsigner file	 responder certificate to sign responses with\n");
		BIO_printf (bio_err, "-rkey file	 responder key to sign responses with\n");
		BIO_printf (bio_err, "-rother file	 other certificates to include in response\n");
		BIO_printf (bio_err, "-resp_no_certs     don't include any certificates in response\n");
		BIO_printf (bio_err, "-nmin n	 	 number of minutes before next update\n");
		BIO_printf (bio_err, "-ndays n	 	 number of days before next update\n");
		BIO_printf (bio_err, "-resp_key_id       identify reponse by signing certificate key ID\n");
		BIO_printf (bio_err, "-nrequest n        number of requests to accept (default unlimited)\n");
		goto end;
		}

	if(outfile) out = BIO_new_file(outfile, "w");
	else out = BIO_new_fp(stdout, BIO_NOCLOSE);

	if(!out)
		{
		BIO_printf(bio_err, "Error opening output file\n");
		goto end;
		}

	if (!req && (add_nonce != 2)) add_nonce = 0;

	if (!req && reqin)
		{
		derbio = BIO_new_file(reqin, "rb");
		if (!derbio)
			{
			BIO_printf(bio_err, "Error Opening OCSP request file\n");
			goto end;
			}
		req = d2i_OCSP_REQUEST_bio(derbio, NULL);
		BIO_free(derbio);
		if(!req)
			{
			BIO_printf(bio_err, "Error reading OCSP request\n");
			goto end;
			}
		}

	if (!req && port)
		{
		acbio = init_responder(port);
		if (!acbio)
			goto end;
		}

	if (rsignfile && !rdb)
		{
		if (!rkeyfile) rkeyfile = rsignfile;
		rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
			NULL, e, "responder certificate");
		if (!rsigner)
			{
			BIO_printf(bio_err, "Error loading responder certificate\n");
			goto end;
			}
		rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
			NULL, e, "CA certificate");
		if (rcertfile)
			{
			rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
				NULL, e, "responder other certificates");
			if (!rother) goto end;
			}
		rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
			"responder private key");
		if (!rkey)
			goto end;
		}
	if(acbio)
		BIO_printf(bio_err, "Waiting for OCSP client connections...\n");

	redo_accept:

	if (acbio)
		{
		if (!do_responder(&req, &cbio, acbio, port))
			goto end;
		if (!req)
			{
			resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
			send_ocsp_response(cbio, resp);
			goto done_resp;
			}
		}

	if (!req && (signfile || reqout || host || add_nonce || ridx_filename))
		{
		BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
		goto end;
		}

	if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);

	if (signfile)
		{
		if (!keyfile) keyfile = signfile;
		signer = load_cert(bio_err, signfile, FORMAT_PEM,
			NULL, e, "signer certificate");
		if (!signer)
			{
			BIO_printf(bio_err, "Error loading signer certificate\n");
			goto end;
			}
		if (sign_certfile)
			{
			sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
				NULL, e, "signer certificates");
			if (!sign_other) goto end;
			}
		key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
			"signer private key");
		if (!key)
			goto end;
		if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
			{
			BIO_printf(bio_err, "Error signing OCSP request\n");
			goto end;
			}
		}

	if (req_text && req) OCSP_REQUEST_print(out, req, 0);

	if (reqout)
		{
		derbio = BIO_new_file(reqout, "wb");
		if(!derbio)
			{
			BIO_printf(bio_err, "Error opening file %s\n", reqout);
			goto end;
			}
		i2d_OCSP_REQUEST_bio(derbio, req);
		BIO_free(derbio);
		}

	if (ridx_filename && (!rkey || !rsigner || !rca_cert))
		{
		BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n");
		goto end;
		}

	if (ridx_filename && !rdb)
		{
		rdb = load_index(ridx_filename, NULL);
		if (!rdb) goto end;
		if (!index_index(rdb)) goto end;
		}

	if (rdb)
		{
		i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays);
		if (cbio)
			send_ocsp_response(cbio, resp);
		}
	else if (host)
		{
#ifndef OPENSSL_NO_SOCK
		cbio = BIO_new_connect(host);
#else
		BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n");
		goto end;
#endif
		if (!cbio)
			{
			BIO_printf(bio_err, "Error creating connect BIO\n");
			goto end;
			}
		if (port) BIO_set_conn_port(cbio, port);
		if (use_ssl == 1)
			{
			BIO *sbio;
#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
			ctx = SSL_CTX_new(SSLv23_client_method());
#elif !defined(OPENSSL_NO_SSL3)
			ctx = SSL_CTX_new(SSLv3_client_method());
#elif !defined(OPENSSL_NO_SSL2)
			ctx = SSL_CTX_new(SSLv2_client_method());
#else
			BIO_printf(bio_err, "SSL is disabled\n");
			goto end;
#endif
			if (ctx == NULL)
				{
				BIO_printf(bio_err, "Error creating SSL context.\n");
				goto end;
				}
			SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
			sbio = BIO_new_ssl(ctx, 1);
			cbio = BIO_push(sbio, cbio);
			}
		if (BIO_do_connect(cbio) <= 0)
			{
			BIO_printf(bio_err, "Error connecting BIO\n");
			goto end;
			}
		resp = OCSP_sendreq_bio(cbio, path, req);
		BIO_free_all(cbio);
		cbio = NULL;
		if (!resp)
			{
			BIO_printf(bio_err, "Error querying OCSP responsder\n");
			goto end;
			}
		}
	else if (respin)
		{
		derbio = BIO_new_file(respin, "rb");
		if (!derbio)
			{
			BIO_printf(bio_err, "Error Opening OCSP response file\n");
			goto end;
			}
		resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
		BIO_free(derbio);
		if(!resp)
			{
			BIO_printf(bio_err, "Error reading OCSP response\n");
			goto end;
			}
	
		}
	else
		{
		ret = 0;
		goto end;
		}

	done_resp:

	if (respout)
		{
		derbio = BIO_new_file(respout, "wb");
		if(!derbio)
			{
			BIO_printf(bio_err, "Error opening file %s\n", respout);
			goto end;
			}
		i2d_OCSP_RESPONSE_bio(derbio, resp);
		BIO_free(derbio);
		}

	i = OCSP_response_status(resp);

	if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
		{
		BIO_printf(out, "Responder Error: %s (%d)\n",
				OCSP_response_status_str(i), i);
		if (ignore_err)
			goto redo_accept;
		ret = 0;
		goto end;
		}

	if (resp_text) OCSP_RESPONSE_print(out, resp, 0);

	/* If running as responder don't verify our own response */
	if (cbio)
		{
		if (accept_count > 0)
			accept_count--;
		/* Redo if more connections needed */
		if (accept_count)
			{
			BIO_free_all(cbio);
			cbio = NULL;
			OCSP_REQUEST_free(req);
			req = NULL;
			OCSP_RESPONSE_free(resp);
			resp = NULL;
			goto redo_accept;
			}
		goto end;
		}

	if (!store)
		store = setup_verify(bio_err, CAfile, CApath);
	if (!store)
		goto end;
	if (verify_certfile)
		{
		verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
			NULL, e, "validator certificate");
		if (!verify_other) goto end;
		}

	bs = OCSP_response_get1_basic(resp);

	if (!bs)
		{
		BIO_printf(bio_err, "Error parsing response\n");
		goto end;
		}

	if (!noverify)
		{
		if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
			{
			if (i == -1)
				BIO_printf(bio_err, "WARNING: no nonce in response\n");
			else
				{
				BIO_printf(bio_err, "Nonce Verify error\n");
				goto end;
				}
			}

		i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
                if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);

		if(i <= 0)
			{
			BIO_printf(bio_err, "Response Verify Failure\n");
			ERR_print_errors(bio_err);
			}
		else
			BIO_printf(bio_err, "Response verify OK\n");

		}

	if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
		goto end;

	ret = 0;

end:
	ERR_print_errors(bio_err);
	X509_free(signer);
	X509_STORE_free(store);
	EVP_PKEY_free(key);
	EVP_PKEY_free(rkey);
	X509_free(issuer);
	X509_free(cert);
	X509_free(rsigner);
	X509_free(rca_cert);
	free_index(rdb);
	BIO_free_all(cbio);
	BIO_free_all(acbio);
	BIO_free(out);
	OCSP_REQUEST_free(req);
	OCSP_RESPONSE_free(resp);
	OCSP_BASICRESP_free(bs);
	sk_free(reqnames);
	sk_OCSP_CERTID_free(ids);
	sk_X509_pop_free(sign_other, X509_free);
	sk_X509_pop_free(verify_other, X509_free);

	if (use_ssl != -1)
		{
		OPENSSL_free(host);
		OPENSSL_free(port);
		OPENSSL_free(path);
		SSL_CTX_free(ctx);
		}

	OPENSSL_EXIT(ret);
}
Beispiel #11
0
static int asn1_template_noexp_d2i(ASN1_VALUE **val,
				const unsigned char **in, long len,
				const ASN1_TEMPLATE *tt, char opt,
				ASN1_TLC *ctx)
	{
	int flags, aclass;
	int ret;
	const unsigned char *p, *q;
	if (!val)
		return 0;
	flags = tt->flags;
	aclass = flags & ASN1_TFLG_TAG_CLASS;

	p = *in;
	q = p;

	if (flags & ASN1_TFLG_SK_MASK)
		{
		/* SET OF, SEQUENCE OF */
		int sktag, skaclass;
		char sk_eoc;
		/* First work out expected inner tag value */
		if (flags & ASN1_TFLG_IMPTAG)
			{
			sktag = tt->tag;
			skaclass = aclass;
			}
		else
			{
			skaclass = V_ASN1_UNIVERSAL;
			if (flags & ASN1_TFLG_SET_OF)
				sktag = V_ASN1_SET;
			else
				sktag = V_ASN1_SEQUENCE;
			}
		/* Get the tag */
		ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
					&p, len, sktag, skaclass, opt, ctx);
		if (!ret)
			{
			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
						ERR_R_NESTED_ASN1_ERROR);
			return 0;
			}
		else if (ret == -1)
			return -1;
		if (!*val)
			*val = (ASN1_VALUE *)sk_new_null();
		else
			{
			/* We've got a valid STACK: free up any items present */
			STACK *sktmp = (STACK *)*val;
			ASN1_VALUE *vtmp;
			while(sk_num(sktmp) > 0)
				{
				vtmp = (ASN1_VALUE *)sk_pop(sktmp);
				ASN1_item_ex_free(&vtmp,
						ASN1_ITEM_ptr(tt->item));
				}
			}
				
		if (!*val)
			{
			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
						ERR_R_MALLOC_FAILURE);
			goto err;
			}

		/* Read as many items as we can */
		while(len > 0)
			{
			ASN1_VALUE *skfield;
			q = p;
			/* See if EOC found */
			if (asn1_check_eoc(&p, len))
				{
				if (!sk_eoc)
					{
					ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
							ASN1_R_UNEXPECTED_EOC);
					goto err;
					}
				len -= p - q;
				sk_eoc = 0;
				break;
				}
			skfield = NULL;
			if (!ASN1_item_ex_d2i(&skfield, &p, len,
						ASN1_ITEM_ptr(tt->item),
						-1, 0, 0, ctx))
				{
				ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
					ERR_R_NESTED_ASN1_ERROR);
				goto err;
				}
			len -= p - q;
			if (!sk_push((STACK *)*val, (char *)skfield))
				{
				ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
						ERR_R_MALLOC_FAILURE);
				goto err;
				}
			}
		if (sk_eoc)
			{
			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC);
			goto err;
			}
		}
	else if (flags & ASN1_TFLG_IMPTAG)
		{
		/* IMPLICIT tagging */
		ret = ASN1_item_ex_d2i(val, &p, len,
			ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx);
		if (!ret)
			{
			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
						ERR_R_NESTED_ASN1_ERROR);
			goto err;
			}
		else if (ret == -1)
			return -1;
		}
	else
		{
		/* Nothing special */
		ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
							-1, 0, opt, ctx);
		if (!ret)
			{
			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
					ERR_R_NESTED_ASN1_ERROR);
			goto err;
			}
		else if (ret == -1)
			return -1;
		}

	*in = p;
	return 1;

	err:
	ASN1_template_free(val, tt);
	return 0;
	}
Beispiel #12
0
/*
 * der points to the start of one or more DER-encoded keys. If there is
 * more than one key, the keys must be contained in multi-key CGA
 * extensions.
 *
 * Returns a stack of EVP_PKEYs on success.
 */
_STACK *
cga_der2keys(uint8_t *der, int dlen)
{
	uint8_t *dk;
	EVP_PKEY *k;
	int klen, elen;
	uint16_t type;
	_STACK *sk;

	if ((sk = sk_new_null()) == NULL) {
		APPLOG_NOMEM();
		return (NULL);
	}

	/* Extract first key, not in an extension */
	dk = cga_parse_key(der, &klen);
	DBG(&dbg_asn1, "getting key 1 (klen %d dlen %d)", klen, dlen);

	if ((k = cga_der2key(der, klen)) == NULL) {
		goto fail;
	}
	if (sk_push(sk, (void *)k) == 0) {
		APPLOG_NOMEM();
		goto fail;
	}

	/* Extract any keys in extensions */
	der += klen;
	dlen -= klen;
	while (dlen > 0) {
		if (cga_parse_next_ext(der, dlen, &elen, &type) < 0) {
			goto fail;
		}
		DBG(&dbg_asn1, "got extension type %d len %d", type, elen);
		if (dlen < elen) {
			DBG(&dbg_asn1, "elen > dlen (%d / %d)", elen, dlen);
			goto fail;
		}
		if (type != CGA_MULTIKEY_EXT) {
			goto next;
		}

		dk = cga_get_multikey_key(der, &klen);
		DBG(&dbg_asn1, "getting ext key (%d bytes)", klen);
		if ((k = cga_der2key(dk, klen)) == NULL) {
			goto fail;
		}
		if (sk_insert(sk, (void *)k, 0) == 0) {
			APPLOG_NOMEM();
			goto fail;
		}

	next:
		dlen -= elen;
		der += elen;
	}

	return (sk);

fail:
	cga_free_keystack(sk);
	return (NULL);
}
Beispiel #13
0
int MAIN(int argc, char **argv)
	{
	int i,badops=0;
	BIO *in=NULL,*out=NULL;
	int informat,outformat;
	char *infile,*outfile,*prog,*certfile;
	PKCS7 *p7 = NULL;
	PKCS7_SIGNED *p7s = NULL;
	X509_CRL *crl=NULL;
	STACK *certflst=NULL;
	STACK_OF(X509_CRL) *crl_stack=NULL;
	STACK_OF(X509) *cert_stack=NULL;
	int ret=1,nocrl=0;

	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

	infile=NULL;
	outfile=NULL;
	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

	prog=argv[0];
	argc--;
	argv++;
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-nocrl") == 0)
			{
			nocrl=1;
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (strcmp(*argv,"-certfile") == 0)
			{
			if (--argc < 1) goto bad;
			if(!certflst) certflst = sk_new_null();
			sk_push(certflst,*(++argv));
			}
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
		BIO_printf(bio_err,"where options are\n");
		BIO_printf(bio_err," -inform arg    input format - DER or PEM\n");
		BIO_printf(bio_err," -outform arg   output format - DER or PEM\n");
		BIO_printf(bio_err," -in arg        input file\n");
		BIO_printf(bio_err," -out arg       output file\n");
		BIO_printf(bio_err," -certfile arg  certificates file of chain to a trusted CA\n");
		BIO_printf(bio_err,"                (can be used more than once)\n");
		BIO_printf(bio_err," -nocrl         no crl to load, just certs from '-certfile'\n");
		EXIT(1);
		}

	ERR_load_crypto_strings();

	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if (!nocrl)
		{
		if (infile == NULL)
			BIO_set_fp(in,stdin,BIO_NOCLOSE);
		else
			{
			if (BIO_read_filename(in,infile) <= 0)
				{
				perror(infile);
				goto end;
				}
			}

		if 	(informat == FORMAT_ASN1)
			crl=d2i_X509_CRL_bio(in,NULL);
		else if (informat == FORMAT_PEM)
			crl=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 (crl == NULL)
			{
			BIO_printf(bio_err,"unable to load CRL\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		}
	
	if ((p7=PKCS7_new()) == NULL) goto end;
	if ((p7s=PKCS7_SIGNED_new()) == NULL) goto end;
	p7->type=OBJ_nid2obj(NID_pkcs7_signed);
	p7->d.sign=p7s;
	p7s->contents->type=OBJ_nid2obj(NID_pkcs7_data);

	if (!ASN1_INTEGER_set(p7s->version,1)) goto end;
	if ((crl_stack=sk_X509_CRL_new_null()) == NULL) goto end;
	p7s->crl=crl_stack;
	if (crl != NULL)
		{
		sk_X509_CRL_push(crl_stack,crl);
		crl=NULL; /* now part of p7 for OPENSSL_freeing */
		}

	if ((cert_stack=sk_X509_new_null()) == NULL) goto end;
	p7s->cert=cert_stack;

	if(certflst) for(i = 0; i < sk_num(certflst); i++) {
		certfile = sk_value(certflst, i);
		if (add_certs_from_file(cert_stack,certfile) < 0)
			{
			BIO_printf(bio_err, "error loading certificates\n");
			ERR_print_errors(bio_err);
			goto end;
			}
	}

	sk_free(certflst);

	if (outfile == NULL)
		{
		BIO_set_fp(out,stdout,BIO_NOCLOSE);
#ifdef VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outfile) <= 0)
			{
			perror(outfile);
			goto end;
			}
		}

	if 	(outformat == FORMAT_ASN1)
		i=i2d_PKCS7_bio(out,p7);
	else if (outformat == FORMAT_PEM)
		i=PEM_write_bio_PKCS7(out,p7);
	else	{
		BIO_printf(bio_err,"bad output format specified for outfile\n");
		goto end;
		}
	if (!i)
		{
		BIO_printf(bio_err,"unable to write pkcs7 object\n");
		ERR_print_errors(bio_err);
		goto end;
		}
	ret=0;
end:
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	if (p7 != NULL) PKCS7_free(p7);
	if (crl != NULL) X509_CRL_free(crl);

	EXIT(ret);
	}