OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 #include <stdio.h> | 5 #include <stdio.h> |
6 #include <string.h> | 6 #include <string.h> |
7 #include <signal.h> | 7 #include <signal.h> |
8 #include <unistd.h> | 8 #include <unistd.h> |
9 #include <limits.h> | 9 #include <limits.h> |
10 #include <errno.h> | 10 #include <errno.h> |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 } | 963 } |
964 #endif | 964 #endif |
965 | 965 |
966 } | 966 } |
967 | 967 |
968 #define TOTAL_FILE_LIMIT 1000000 /* one million */ | 968 #define TOTAL_FILE_LIMIT 1000000 /* one million */ |
969 | 969 |
970 size_t RNG_FileUpdate(const char *fileName, size_t limit) | 970 size_t RNG_FileUpdate(const char *fileName, size_t limit) |
971 { | 971 { |
972 FILE * file; | 972 FILE * file; |
973 size_t bytes; | 973 int fd; |
| 974 int bytes; |
974 size_t fileBytes = 0; | 975 size_t fileBytes = 0; |
975 struct stat stat_buf; | 976 struct stat stat_buf; |
976 unsigned char buffer[BUFSIZ]; | 977 unsigned char buffer[BUFSIZ]; |
977 static size_t totalFileBytes = 0; | 978 static size_t totalFileBytes = 0; |
978 | 979 |
979 /* suppress valgrind warnings due to holes in struct stat */ | 980 /* suppress valgrind warnings due to holes in struct stat */ |
980 memset(&stat_buf, 0, sizeof(stat_buf)); | 981 memset(&stat_buf, 0, sizeof(stat_buf)); |
981 | 982 |
982 if (stat((char *)fileName, &stat_buf) < 0) | 983 if (stat((char *)fileName, &stat_buf) < 0) |
983 return fileBytes; | 984 return fileBytes; |
984 RNG_RandomUpdate(&stat_buf, sizeof(stat_buf)); | 985 RNG_RandomUpdate(&stat_buf, sizeof(stat_buf)); |
985 | 986 |
986 file = fopen((char *)fileName, "r"); | 987 file = fopen(fileName, "r"); |
987 if (file != NULL) { | 988 if (file != NULL) { |
| 989 /* Read from the underlying file descriptor directly to bypass stdio |
| 990 * buffering and avoid reading more bytes than we need from |
| 991 * /dev/urandom. NOTE: we can't use fread with unbuffered I/O because |
| 992 * fread may return EOF in unbuffered I/O mode on Android. |
| 993 * |
| 994 * Moreover, we read into a buffer of size BUFSIZ, so buffered I/O |
| 995 * has no performance advantage. */ |
| 996 fd = fileno(file); |
| 997 /* 'file' was just opened, so this should not fail. */ |
| 998 PORT_Assert(fd != -1); |
988 while (limit > fileBytes) { | 999 while (limit > fileBytes) { |
989 bytes = PR_MIN(sizeof buffer, limit - fileBytes); | 1000 bytes = PR_MIN(sizeof buffer, limit - fileBytes); |
990 » bytes = fread(buffer, 1, bytes, file); | 1001 » bytes = read(fd, buffer, bytes); |
991 » if (bytes == 0) | 1002 » if (bytes <= 0) |
992 break; | 1003 break; |
993 RNG_RandomUpdate(buffer, bytes); | 1004 RNG_RandomUpdate(buffer, bytes); |
994 fileBytes += bytes; | 1005 fileBytes += bytes; |
995 totalFileBytes += bytes; | 1006 totalFileBytes += bytes; |
996 /* after TOTAL_FILE_LIMIT has been reached, only read in first | 1007 /* after TOTAL_FILE_LIMIT has been reached, only read in first |
997 ** buffer of data from each subsequent file. | 1008 ** buffer of data from each subsequent file. |
998 */ | 1009 */ |
999 if (totalFileBytes > TOTAL_FILE_LIMIT) | 1010 if (totalFileBytes > TOTAL_FILE_LIMIT) |
1000 break; | 1011 break; |
1001 } | 1012 } |
(...skipping 11 matching lines...) Expand all Loading... |
1013 void RNG_FileForRNG(const char *fileName) | 1024 void RNG_FileForRNG(const char *fileName) |
1014 { | 1025 { |
1015 RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT); | 1026 RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT); |
1016 } | 1027 } |
1017 | 1028 |
1018 void ReadSingleFile(const char *fileName) | 1029 void ReadSingleFile(const char *fileName) |
1019 { | 1030 { |
1020 FILE * file; | 1031 FILE * file; |
1021 unsigned char buffer[BUFSIZ]; | 1032 unsigned char buffer[BUFSIZ]; |
1022 | 1033 |
1023 file = fopen((char *)fileName, "rb"); | 1034 file = fopen(fileName, "rb"); |
1024 if (file != NULL) { | 1035 if (file != NULL) { |
1025 while (fread(buffer, 1, sizeof(buffer), file) > 0) | 1036 while (fread(buffer, 1, sizeof(buffer), file) > 0) |
1026 ; | 1037 ; |
1027 fclose(file); | 1038 fclose(file); |
1028 } | 1039 } |
1029 } | 1040 } |
1030 | 1041 |
1031 #define _POSIX_PTHREAD_SEMANTICS | 1042 #define _POSIX_PTHREAD_SEMANTICS |
1032 #include <dirent.h> | 1043 #include <dirent.h> |
1033 | 1044 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 } | 1146 } |
1136 | 1147 |
1137 /* | 1148 /* |
1138 * Modified to abort the process if it failed to read from /dev/urandom. | 1149 * Modified to abort the process if it failed to read from /dev/urandom. |
1139 * | 1150 * |
1140 * See crbug.com/244661 for details. | 1151 * See crbug.com/244661 for details. |
1141 */ | 1152 */ |
1142 size_t RNG_SystemRNG(void *dest, size_t maxLen) | 1153 size_t RNG_SystemRNG(void *dest, size_t maxLen) |
1143 { | 1154 { |
1144 FILE *file; | 1155 FILE *file; |
1145 size_t bytes; | 1156 int fd; |
| 1157 int bytes; |
1146 size_t fileBytes = 0; | 1158 size_t fileBytes = 0; |
1147 unsigned char *buffer = dest; | 1159 unsigned char *buffer = dest; |
1148 | 1160 |
1149 file = fopen("/dev/urandom", "r"); | 1161 file = fopen("/dev/urandom", "r"); |
1150 if (file == NULL) { | 1162 if (file == NULL) { |
1151 fprintf(stderr, "[ERROR:%s(%d)] NSS failed to read from /dev/urandom. " | 1163 fprintf(stderr, "[ERROR:%s(%d)] NSS failed to read from /dev/urandom. " |
1152 "Abort process.\n", __FILE__, __LINE__); | 1164 "Abort process.\n", __FILE__, __LINE__); |
1153 fflush(stderr); | 1165 fflush(stderr); |
1154 abort(); | 1166 abort(); |
1155 } | 1167 } |
| 1168 /* Read from the underlying file descriptor directly to bypass stdio |
| 1169 * buffering and avoid reading more bytes than we need from /dev/urandom. |
| 1170 * NOTE: we can't use fread with unbuffered I/O because fread may return |
| 1171 * EOF in unbuffered I/O mode on Android. |
| 1172 */ |
| 1173 fd = fileno(file); |
| 1174 /* 'file' was just opened, so this should not fail. */ |
| 1175 PORT_Assert(fd != -1); |
1156 while (maxLen > fileBytes) { | 1176 while (maxLen > fileBytes) { |
1157 bytes = maxLen - fileBytes; | 1177 bytes = maxLen - fileBytes; |
1158 » bytes = fread(buffer, 1, bytes, file); | 1178 » bytes = read(fd, buffer, bytes); |
1159 » if (bytes == 0) | 1179 » if (bytes <= 0) |
1160 break; | 1180 break; |
1161 fileBytes += bytes; | 1181 fileBytes += bytes; |
1162 buffer += bytes; | 1182 buffer += bytes; |
1163 } | 1183 } |
1164 fclose(file); | 1184 fclose(file); |
1165 if (fileBytes != maxLen) { | 1185 if (fileBytes != maxLen) { |
1166 fprintf(stderr, "[ERROR:%s(%d)] NSS failed to read from /dev/urandom. " | 1186 fprintf(stderr, "[ERROR:%s(%d)] NSS failed to read from /dev/urandom. " |
1167 "Abort process.\n", __FILE__, __LINE__); | 1187 "Abort process.\n", __FILE__, __LINE__); |
1168 fflush(stderr); | 1188 fflush(stderr); |
1169 abort(); | 1189 abort(); |
1170 } | 1190 } |
1171 return fileBytes; | 1191 return fileBytes; |
1172 } | 1192 } |
OLD | NEW |