In cases where we ask PEM_def_callback for minimum 0 length, accept 0 length
[openssl.git] / crypto / pem / pem_lib.c
index 1f0f8d6c8d319cc063b6ad3c510b12d64547e256..7c82561ba40ee53031aab3af03325a904675e1fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -28,15 +28,16 @@ static int load_iv(char **fromp, unsigned char *to, int num);
 static int check_pem(const char *nm, const char *name);
 int pem_check_suffix(const char *pem_str, const char *suffix);
 
-int PEM_def_callback(char *buf, int num, int w, void *key)
+int PEM_def_callback(char *buf, int num, int rwflag, void *userdata)
 {
-    int i, j;
+    int i, min_len;
     const char *prompt;
 
-    if (key) {
-        i = strlen(key);
+    /* We assume that the user passes a default password as userdata */
+    if (userdata) {
+        i = strlen(userdata);
         i = (i > num) ? num : i;
-        memcpy(buf, key, i);
+        memcpy(buf, userdata, i);
         return i;
     }
 
@@ -44,28 +45,22 @@ int PEM_def_callback(char *buf, int num, int w, void *key)
     if (prompt == NULL)
         prompt = "Enter PEM pass phrase:";
 
-    for (;;) {
-        /*
-         * We assume that w == 0 means decryption,
-         * while w == 1 means encryption
-         */
-        int min_len = w ? MIN_LENGTH : 0;
+    /*
+     * rwflag == 0 means decryption
+     * rwflag == 1 means encryption
+     *
+     * We assume that for encryption, we want a minimum length, while for
+     * decryption, we cannot know any minimum length, so we assume zero.
+     */
+    min_len = rwflag ? MIN_LENGTH : 0;
 
-        i = EVP_read_pw_string_min(buf, min_len, num, prompt, w);
-        if (i != 0) {
-            PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD);
-            memset(buf, 0, (unsigned int)num);
-            return -1;
-        }
-        j = strlen(buf);
-        if (min_len && j < min_len) {
-            fprintf(stderr,
-                    "phrase is too short, needs to be at least %d chars\n",
-                    min_len);
-        } else
-            break;
+    i = EVP_read_pw_string_min(buf, min_len, num, prompt, rwflag);
+    if (i != 0) {
+        PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD);
+        memset(buf, 0, (unsigned int)num);
+        return -1;
     }
-    return j;
+    return strlen(buf);
 }
 
 void PEM_proc_type(char *buf, int type)
@@ -435,7 +430,7 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
         keylen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u);
     else
         keylen = callback(buf, PEM_BUFSIZE, 0, u);
-    if (keylen <= 0) {
+    if (keylen < 0) {
         PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ);
         return 0;
     }
@@ -610,6 +605,7 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header,
     unsigned char *buf = NULL;
     EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
     int reason = ERR_R_BUF_LIB;
+    int retval = 0;
 
     if (ctx == NULL) {
         reason = ERR_R_MALLOC_FAILURE;
@@ -654,14 +650,14 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header,
         (BIO_write(bp, name, nlen) != nlen) ||
         (BIO_write(bp, "-----\n", 6) != 6))
         goto err;
-    OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
-    EVP_ENCODE_CTX_free(ctx);
-    return i + outl;
+    retval = i + outl;
+
  err:
-    OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
+    if (retval == 0)
+        PEMerr(PEM_F_PEM_WRITE_BIO, reason);
     EVP_ENCODE_CTX_free(ctx);
-    PEMerr(PEM_F_PEM_WRITE_BIO, reason);
-    return 0;
+    OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
+    return retval;
 }
 
 #ifndef OPENSSL_NO_STDIO