hkdf: when HMAC key is all zeros, still set a valid key length
[openssl.git] / crypto / bio / bss_file.c
index a2b8700f22fbeee0a91c39861cf7c754a76a7698..05d87cfe90faee8a9a191ad97d9fc86d7a5036ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,14 +7,11 @@
  * https://www.openssl.org/source/license.html
  */
 
-#ifndef HEADER_BSS_FILE_C
-# define HEADER_BSS_FILE_C
-
-# if defined(__linux) || defined(__sun) || defined(__hpux)
+#if defined(__linux) || defined(__sun) || defined(__hpux)
 /*
  * Following definition aliases fopen to fopen64 on above mentioned
  * platforms. This makes it possible to open and sequentially access files
- * larger than 2GB from 32-bit application. It does not allow to traverse
+ * larger than 2GB from 32-bit application. It does not allow one to traverse
  * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit
  * platform permits that, not with fseek/ftell. Not to mention that breaking
  * 2GB limit for seeking would require surgery to *our* API. But sequential
  * of 32-bit platforms which allow for sequential access of large files
  * without extra "magic" comprise *BSD, Darwin, IRIX...
  */
-#  ifndef _FILE_OFFSET_BITS
-#   define _FILE_OFFSET_BITS 64
-#  endif
+# ifndef _FILE_OFFSET_BITS
+#  define _FILE_OFFSET_BITS 64
 # endif
+#endif
 
-# include <stdio.h>
-# include <errno.h>
-# include "bio_lcl.h"
-# include <openssl/err.h>
+#include <stdio.h>
+#include <errno.h>
+#include "bio_local.h"
+#include <openssl/err.h>
 
-# if !defined(OPENSSL_NO_STDIO)
+#if !defined(OPENSSL_NO_STDIO)
 
 static int file_write(BIO *h, const char *buf, int num);
 static int file_read(BIO *h, char *buf, int size);
@@ -45,10 +42,8 @@ static int file_free(BIO *data);
 static const BIO_METHOD methods_filep = {
     BIO_TYPE_FILE,
     "FILE pointer",
-    /* TODO: Convert to new style write function */
     bwrite_conv,
     file_write,
-    /* TODO: Convert to new style read function */
     bread_conv,
     file_read,
     file_puts,
@@ -69,16 +64,17 @@ BIO *BIO_new_file(const char *filename, const char *mode)
         fp_flags |= BIO_FP_TEXT;
 
     if (file == NULL) {
-        SYSerr(SYS_F_FOPEN, get_last_sys_error());
-        ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
+        ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+                       "calling fopen(%s, %s)",
+                       filename, mode);
         if (errno == ENOENT
-# ifdef ENXIO
+#ifdef ENXIO
             || errno == ENXIO
-# endif
+#endif
             )
-            BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
+            ERR_raise(ERR_LIB_BIO, BIO_R_NO_SUCH_FILE);
         else
-            BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
+            ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
         return NULL;
     }
     if ((ret = BIO_new(BIO_s_file())) == NULL) {
@@ -86,8 +82,8 @@ BIO *BIO_new_file(const char *filename, const char *mode)
         return NULL;
     }
 
-    BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage
-                                             * UPLINK */
+    /* we did fopen -> we disengage UPLINK */
+    BIO_clear_flags(ret, BIO_FLAGS_UPLINK_INTERNAL);
     BIO_set_fp(ret, file, fp_flags);
     return ret;
 }
@@ -100,7 +96,7 @@ BIO *BIO_new_fp(FILE *stream, int close_flag)
         return NULL;
 
     /* redundant flag, left for documentation purposes */
-    BIO_set_flags(ret, BIO_FLAGS_UPLINK);
+    BIO_set_flags(ret, BIO_FLAGS_UPLINK_INTERNAL);
     BIO_set_fp(ret, stream, close_flag);
     return ret;
 }
@@ -115,7 +111,7 @@ static int file_new(BIO *bi)
     bi->init = 0;
     bi->num = 0;
     bi->ptr = NULL;
-    bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */
+    bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* default to UPLINK */
     return 1;
 }
 
@@ -125,12 +121,12 @@ static int file_free(BIO *a)
         return 0;
     if (a->shutdown) {
         if ((a->init) && (a->ptr != NULL)) {
-            if (a->flags & BIO_FLAGS_UPLINK)
+            if (a->flags & BIO_FLAGS_UPLINK_INTERNAL)
                 UP_fclose(a->ptr);
             else
                 fclose(a->ptr);
             a->ptr = NULL;
-            a->flags = BIO_FLAGS_UPLINK;
+            a->flags = BIO_FLAGS_UPLINK_INTERNAL;
         }
         a->init = 0;
     }
@@ -142,15 +138,16 @@ static int file_read(BIO *b, char *out, int outl)
     int ret = 0;
 
     if (b->init && (out != NULL)) {
-        if (b->flags & BIO_FLAGS_UPLINK)
+        if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
             ret = UP_fread(out, 1, (int)outl, b->ptr);
         else
             ret = fread(out, 1, (int)outl, (FILE *)b->ptr);
         if (ret == 0
-            && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) :
-                                               ferror((FILE *)b->ptr)) {
-            SYSerr(SYS_F_FREAD, get_last_sys_error());
-            BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB);
+            && (b->flags & BIO_FLAGS_UPLINK_INTERNAL
+                ? UP_ferror((FILE *)b->ptr) : ferror((FILE *)b->ptr))) {
+            ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+                           "calling fread()");
+            ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
             ret = -1;
         }
     }
@@ -162,7 +159,7 @@ static int file_write(BIO *b, const char *in, int inl)
     int ret = 0;
 
     if (b->init && (in != NULL)) {
-        if (b->flags & BIO_FLAGS_UPLINK)
+        if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
             ret = UP_fwrite(in, (int)inl, 1, b->ptr);
         else
             ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr);
@@ -189,20 +186,20 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
     switch (cmd) {
     case BIO_C_FILE_SEEK:
     case BIO_CTRL_RESET:
-        if (b->flags & BIO_FLAGS_UPLINK)
+        if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
             ret = (long)UP_fseek(b->ptr, num, 0);
         else
             ret = (long)fseek(fp, num, 0);
         break;
     case BIO_CTRL_EOF:
-        if (b->flags & BIO_FLAGS_UPLINK)
+        if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
             ret = (long)UP_feof(fp);
         else
             ret = (long)feof(fp);
         break;
     case BIO_C_FILE_TELL:
     case BIO_CTRL_INFO:
-        if (b->flags & BIO_FLAGS_UPLINK)
+        if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
             ret = UP_ftell(b->ptr);
         else
             ret = ftell(fp);
@@ -212,33 +209,42 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
         b->shutdown = (int)num & BIO_CLOSE;
         b->ptr = ptr;
         b->init = 1;
-#  if BIO_FLAGS_UPLINK!=0
-#   if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
-#    define _IOB_ENTRIES 20
-#   endif
+# if BIO_FLAGS_UPLINK_INTERNAL!=0
+#  if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
+#   define _IOB_ENTRIES 20
+#  endif
         /* Safety net to catch purely internal BIO_set_fp calls */
-#   if defined(_MSC_VER) && _MSC_VER>=1900
+#  if (defined(_MSC_VER) && _MSC_VER>=1900) || defined(__BORLANDC__)
         if (ptr == stdin || ptr == stdout || ptr == stderr)
-            BIO_clear_flags(b, BIO_FLAGS_UPLINK);
-#   elif defined(_IOB_ENTRIES)
+            BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL);
+#  elif defined(_IOB_ENTRIES)
         if ((size_t)ptr >= (size_t)stdin &&
             (size_t)ptr < (size_t)(stdin + _IOB_ENTRIES))
-            BIO_clear_flags(b, BIO_FLAGS_UPLINK);
-#   endif
+            BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL);
 #  endif
-#  ifdef UP_fsetmod
-        if (b->flags & BIO_FLAGS_UPLINK)
+# endif
+# ifdef UP_fsetmod
+        if (b->flags & BIO_FLAGS_UPLINK_INTERNAL)
             UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b'));
         else
-#  endif
+# endif
         {
-#  if defined(OPENSSL_SYS_WINDOWS)
+# if defined(OPENSSL_SYS_WINDOWS)
             int fd = _fileno((FILE *)ptr);
             if (num & BIO_FP_TEXT)
                 _setmode(fd, _O_TEXT);
             else
                 _setmode(fd, _O_BINARY);
-#  elif defined(OPENSSL_SYS_MSDOS)
+            /*
+             * Reports show that ftell() isn't trustable in text mode.
+             * This has been confirmed as a bug in the Universal C RTL, see
+             * https://developercommunity.visualstudio.com/content/problem/425878/fseek-ftell-fail-in-text-mode-for-unix-style-text.html
+             * The suggested work-around from Microsoft engineering is to
+             * turn off buffering until the bug is resolved.
+             */
+            if ((num & BIO_FP_TEXT) != 0)
+                setvbuf((FILE *)ptr, NULL, _IONBF, 0);
+# elif defined(OPENSSL_SYS_MSDOS)
             int fd = fileno((FILE *)ptr);
             /* Set correct text/binary mode */
             if (num & BIO_FP_TEXT)
@@ -251,13 +257,11 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
                 } else
                     _setmode(fd, _O_BINARY);
             }
-#  elif defined(OPENSSL_SYS_WIN32_CYGWIN)
+# elif defined(OPENSSL_SYS_WIN32_CYGWIN)
             int fd = fileno((FILE *)ptr);
-            if (num & BIO_FP_TEXT)
-                setmode(fd, O_TEXT);
-            else
+            if (!(num & BIO_FP_TEXT))
                 setmode(fd, O_BINARY);
-#  endif
+# endif
         }
         break;
     case BIO_C_SET_FILENAME:
@@ -275,28 +279,32 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
         else if (num & BIO_FP_READ)
             OPENSSL_strlcpy(p, "r", sizeof(p));
         else {
-            BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE);
+            ERR_raise(ERR_LIB_BIO, BIO_R_BAD_FOPEN_MODE);
             ret = 0;
             break;
         }
-#  if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32_CYGWIN)
+# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS)
         if (!(num & BIO_FP_TEXT))
             OPENSSL_strlcat(p, "b", sizeof(p));
         else
             OPENSSL_strlcat(p, "t", sizeof(p));
-#  endif
+# elif defined(OPENSSL_SYS_WIN32_CYGWIN)
+        if (!(num & BIO_FP_TEXT))
+            OPENSSL_strlcat(p, "b", sizeof(p));
+# endif
         fp = openssl_fopen(ptr, p);
         if (fp == NULL) {
-            SYSerr(SYS_F_FOPEN, get_last_sys_error());
-            ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
-            BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB);
+            ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+                           "calling fopen(%s, %s)",
+                           ptr, p);
+            ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
             ret = 0;
             break;
         }
         b->ptr = fp;
         b->init = 1;
-        BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage
-                                               * UPLINK */
+        /* we did fopen -> we disengage UPLINK */
+        BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL);
         break;
     case BIO_C_GET_FILE_PTR:
         /* the ptr parameter is actually a FILE ** in this case. */
@@ -312,12 +320,12 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
         b->shutdown = (int)num;
         break;
     case BIO_CTRL_FLUSH:
-        st = b->flags & BIO_FLAGS_UPLINK
+        st = b->flags & BIO_FLAGS_UPLINK_INTERNAL
                 ? UP_fflush(b->ptr) : fflush((FILE *)b->ptr);
         if (st == EOF) {
-            SYSerr(SYS_F_FFLUSH, get_last_sys_error());
-            ERR_add_error_data(1, "fflush()");
-            BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB);
+            ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+                           "calling fflush()");
+            ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
             ret = 0;
         }
         break;
@@ -341,7 +349,7 @@ static int file_gets(BIO *bp, char *buf, int size)
     int ret = 0;
 
     buf[0] = '\0';
-    if (bp->flags & BIO_FLAGS_UPLINK) {
+    if (bp->flags & BIO_FLAGS_UPLINK_INTERNAL) {
         if (!UP_fgets(buf, size, bp->ptr))
             goto err;
     } else {
@@ -397,10 +405,8 @@ static int file_free(BIO *a)
 static const BIO_METHOD methods_filep = {
     BIO_TYPE_FILE,
     "FILE pointer",
-    /* TODO: Convert to new style write function */
     bwrite_conv,
     file_write,
-    /* TODO: Convert to new style read function */
     bread_conv,
     file_read,
     file_puts,
@@ -421,6 +427,4 @@ BIO *BIO_new_file(const char *filename, const char *mode)
     return NULL;
 }
 
-# endif                         /* OPENSSL_NO_STDIO */
-
-#endif                          /* HEADER_BSS_FILE_C */
+#endif                         /* OPENSSL_NO_STDIO */