Make PKCS#12 code handle missing passwords.
Add a couple of FAQs.
This commit is contained in:
		
							
								
								
									
										13
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								CHANGES
									
									
									
									
									
								
							@@ -4,6 +4,19 @@
 | 
			
		||||
 | 
			
		||||
 Changes between 0.9.5a and 0.9.6  [xx XXX 2000]
 | 
			
		||||
 | 
			
		||||
  *) Make PKCS#12 code work with no password. The PKCS#12 spec
 | 
			
		||||
     is a little unclear about how a blank password is handled.
 | 
			
		||||
     Since the password in encoded as a BMPString with terminating
 | 
			
		||||
     double NULL a zero length password would end up as just the
 | 
			
		||||
     double NULL. However no password at all is different and is
 | 
			
		||||
     handled differently in the PKCS#12 key generation code. NS
 | 
			
		||||
     treats a blank password as zero length. MSIE treats it as no
 | 
			
		||||
     password on export: but it will try both on import. We now do
 | 
			
		||||
     the same: PKCS12_parse() tries zero length and no password if
 | 
			
		||||
     the password is set to "" or NULL (NULL is now a valid password:
 | 
			
		||||
     it wasn't before) as does the pkcs12 application.
 | 
			
		||||
     [Steve Henson]
 | 
			
		||||
 | 
			
		||||
  *) Bugfixes in apps/x509.c: Avoid a memory leak; and don't use
 | 
			
		||||
     perror when PEM_read_bio_X509_REQ fails, the error message must
 | 
			
		||||
     be obtained from the error queue.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								FAQ
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								FAQ
									
									
									
									
									
								
							@@ -16,8 +16,10 @@ OpenSSL  -  Frequently Asked Questions
 | 
			
		||||
* How do I create certificates or certificate requests?
 | 
			
		||||
* Why can't I create certificate requests?
 | 
			
		||||
* Why does <SSL program> fail with a certificate verify error?
 | 
			
		||||
* Why can I only use weak ciphers when I connect to a server using OpenSSL?
 | 
			
		||||
* How can I create DSA certificates?
 | 
			
		||||
* Why can't I make an SSL connection using a DSA certificate?
 | 
			
		||||
* How can I remove the passphrase on a private key?
 | 
			
		||||
* Why can't the OpenSSH configure script detect OpenSSL?
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -232,6 +234,13 @@ or file and the relevant program configured to read it. The OpenSSL program
 | 
			
		||||
the verify(1) program manual page for more information.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* Why can I only use weak ciphers when I connect to a server using OpenSSL?
 | 
			
		||||
 | 
			
		||||
This is almost certainly because you are using an old "export grade" browser
 | 
			
		||||
which only supports weak encryption. Upgrade your browser to support 128 bit
 | 
			
		||||
ciphers.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* How can I create DSA certificates?
 | 
			
		||||
 | 
			
		||||
Check the CA.pl(1) manual page for a DSA certificate example.
 | 
			
		||||
@@ -242,11 +251,19 @@ Check the CA.pl(1) manual page for a DSA certificate example.
 | 
			
		||||
Typically you'll see a message saying there are no shared ciphers when
 | 
			
		||||
the same setup works fine with an RSA certificate. There are two possible
 | 
			
		||||
causes. The client may not support connections to DSA servers most web
 | 
			
		||||
browsers only support connections to servers supporting RSA cipher suites.
 | 
			
		||||
The other cause is that a set of DH parameters has not been supplied to
 | 
			
		||||
the server. DH parameters can be created with the dhparam(1) command and
 | 
			
		||||
loaded using the SSL_CTX_set_tmp_dh() for example: check the source to
 | 
			
		||||
s_server in apps/s_server.c for an example.
 | 
			
		||||
browsers (including Netscape and MSIE) only support connections to servers
 | 
			
		||||
supporting RSA cipher suites. The other cause is that a set of DH parameters
 | 
			
		||||
has not been supplied to the server. DH parameters can be created with the
 | 
			
		||||
dhparam(1) command and loaded using the SSL_CTX_set_tmp_dh() for example:
 | 
			
		||||
check the source to s_server in apps/s_server.c for an example.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* How can I remove the passphrase on a private key?
 | 
			
		||||
 | 
			
		||||
Firstly you should be really *really* sure you want to do this. Leaving
 | 
			
		||||
a private key unencrypted is a major security risk. If you decide that
 | 
			
		||||
you do have to do this check the EXAMPLES sections of the rsa(1) and
 | 
			
		||||
dsa(1) manual pages.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* Why can't the OpenSSH configure script detect OpenSSL?
 | 
			
		||||
 
 | 
			
		||||
@@ -528,11 +528,16 @@ int MAIN(int argc, char **argv)
 | 
			
		||||
#ifdef CRYPTO_MDEBUG
 | 
			
		||||
    CRYPTO_push_info("verify MAC");
 | 
			
		||||
#endif
 | 
			
		||||
	if (!PKCS12_verify_mac (p12, mpass, -1)) {
 | 
			
		||||
	/* 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;
 | 
			
		||||
	} else BIO_printf (bio_err, "MAC verified OK\n");
 | 
			
		||||
	}
 | 
			
		||||
	BIO_printf (bio_err, "MAC verified OK\n");
 | 
			
		||||
#ifdef CRYPTO_MDEBUG
 | 
			
		||||
    CRYPTO_pop_info();
 | 
			
		||||
#endif
 | 
			
		||||
@@ -549,9 +554,9 @@ int MAIN(int argc, char **argv)
 | 
			
		||||
#ifdef CRYPTO_MDEBUG
 | 
			
		||||
    CRYPTO_pop_info();
 | 
			
		||||
#endif
 | 
			
		||||
    PKCS12_free(p12);
 | 
			
		||||
    ret = 0;
 | 
			
		||||
    end:
 | 
			
		||||
    PKCS12_free(p12);
 | 
			
		||||
    if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
 | 
			
		||||
#ifdef CRYPTO_MDEBUG
 | 
			
		||||
    CRYPTO_remove_all_info();
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,8 @@ int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
 | 
			
		||||
		ERR_add_error_data(2, "TYPE=", obj_tmp);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (passlen == -1) passlen = strlen(pass);
 | 
			
		||||
	if(!pass) passlen = 0;
 | 
			
		||||
	else if (passlen == -1) passlen = strlen(pass);
 | 
			
		||||
	pbetmp = (EVP_PBE_CTL *)sk_value (pbe_algs, i);
 | 
			
		||||
	i = (*pbetmp->keygen)(ctx, pass, passlen, param, pbetmp->cipher,
 | 
			
		||||
						 pbetmp->md, en_de);
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,9 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
 | 
			
		||||
	salt = pbe->salt->data;
 | 
			
		||||
	saltlen = pbe->salt->length;
 | 
			
		||||
 | 
			
		||||
	if(!pass) passlen = 0;
 | 
			
		||||
	else if(passlen == -1) passlen = strlen(pass);
 | 
			
		||||
 | 
			
		||||
	EVP_DigestInit (&ctx, md);
 | 
			
		||||
	EVP_DigestUpdate (&ctx, pass, passlen);
 | 
			
		||||
	EVP_DigestUpdate (&ctx, salt, saltlen);
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,8 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
 | 
			
		||||
	HMAC_CTX hctx;
 | 
			
		||||
	p = out;
 | 
			
		||||
	tkeylen = keylen;
 | 
			
		||||
	if(passlen == -1) passlen = strlen(pass);
 | 
			
		||||
	if(!pass) passlen = 0;
 | 
			
		||||
	else if(passlen == -1) passlen = strlen(pass);
 | 
			
		||||
	while(tkeylen) {
 | 
			
		||||
		if(tkeylen > SHA_DIGEST_LENGTH) cplen = SHA_DIGEST_LENGTH;
 | 
			
		||||
		else cplen = tkeylen;
 | 
			
		||||
 
 | 
			
		||||
@@ -74,25 +74,30 @@ void h__dump (unsigned char *p, int len);
 | 
			
		||||
#define min(a,b) ((a) < (b) ? (a) : (b))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int PKCS12_key_gen_asc (const char *pass, int passlen, unsigned char *salt,
 | 
			
		||||
int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
 | 
			
		||||
	     int saltlen, int id, int iter, int n, unsigned char *out,
 | 
			
		||||
	     const EVP_MD *md_type)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	unsigned char *unipass;
 | 
			
		||||
	int uniplen;
 | 
			
		||||
	if (!asc2uni (pass, &unipass, &uniplen)) {
 | 
			
		||||
	if(!pass) {
 | 
			
		||||
		unipass = NULL;
 | 
			
		||||
		uniplen = 0;
 | 
			
		||||
	} else if (!asc2uni(pass, &unipass, &uniplen)) {
 | 
			
		||||
		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	ret = PKCS12_key_gen_uni (unipass, uniplen, salt, saltlen,
 | 
			
		||||
	ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
 | 
			
		||||
						 id, iter, n, out, md_type);
 | 
			
		||||
	memset(unipass, 0, uniplen);	/* Clear password from memory */
 | 
			
		||||
	Free(unipass);
 | 
			
		||||
	if(unipass) {
 | 
			
		||||
		memset(unipass, 0, uniplen);	/* Clear password from memory */
 | 
			
		||||
		Free(unipass);
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt,
 | 
			
		||||
int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
 | 
			
		||||
	     int saltlen, int id, int iter, int n, unsigned char *out,
 | 
			
		||||
	     const EVP_MD *md_type)
 | 
			
		||||
{
 | 
			
		||||
@@ -106,10 +111,12 @@ int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt,
 | 
			
		||||
	int tmpn = n;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	if (!pass) {
 | 
			
		||||
		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef  DEBUG_KEYGEN
 | 
			
		||||
	fprintf(stderr, "KEYGEN DEBUG\n");
 | 
			
		||||
@@ -125,7 +132,8 @@ int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt,
 | 
			
		||||
	Ai = Malloc (u);
 | 
			
		||||
	B = Malloc (v + 1);
 | 
			
		||||
	Slen = v * ((saltlen+v-1)/v);
 | 
			
		||||
	Plen = v * ((passlen+v-1)/v);
 | 
			
		||||
	if(passlen) Plen = v * ((passlen+v-1)/v);
 | 
			
		||||
	else Plen = 0;
 | 
			
		||||
	Ilen = Slen + Plen;
 | 
			
		||||
	I = Malloc (Ilen);
 | 
			
		||||
	Ij = BN_new();
 | 
			
		||||
 
 | 
			
		||||
@@ -106,11 +106,23 @@ int PKCS12_parse (PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
 | 
			
		||||
 | 
			
		||||
	/* Check the mac */
 | 
			
		||||
 | 
			
		||||
	if (!PKCS12_verify_mac (p12, pass, -1))
 | 
			
		||||
		{
 | 
			
		||||
	/* If password is zero length or NULL then try verifying both cases
 | 
			
		||||
	 * to determine which password is correct. The reason for this is that
 | 
			
		||||
	 * under PKCS#12 password based encryption no password and a zero length
 | 
			
		||||
	 * password are two different things...
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if(!pass || !*pass) {
 | 
			
		||||
		if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL;
 | 
			
		||||
		else if(PKCS12_verify_mac(p12, "", 0)) pass = "";
 | 
			
		||||
		else {
 | 
			
		||||
			PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
 | 
			
		||||
			goto err;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
 | 
			
		||||
		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
 | 
			
		||||
		goto err;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!parse_pk12 (p12, pass, -1, pkey, cert, ca))
 | 
			
		||||
		{
 | 
			
		||||
 
 | 
			
		||||
@@ -106,10 +106,7 @@ int PKCS12_verify_mac (PKCS12 *p12, const char *pass, int passlen)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if ((maclen != (unsigned int)p12->mac->dinfo->digest->length)
 | 
			
		||||
	|| memcmp (mac, p12->mac->dinfo->digest->data, maclen)) {
 | 
			
		||||
		PKCS12err(PKCS12_F_VERIFY_MAC,PKCS12_R_MAC_VERIFY_ERROR);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	|| memcmp (mac, p12->mac->dinfo->digest->data, maclen)) return 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user