generate_errors.pl 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #!/usr/bin/env perl
  2. # Generate error.c
  3. #
  4. # Usage: ./generate_errors.pl or scripts/generate_errors.pl without arguments,
  5. # or generate_errors.pl include_dir data_dir error_file
  6. #
  7. # Copyright The Mbed TLS Contributors
  8. # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  9. #
  10. # This file is provided under the Apache License 2.0, or the
  11. # GNU General Public License v2.0 or later.
  12. #
  13. # **********
  14. # Apache License 2.0:
  15. #
  16. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  17. # not use this file except in compliance with the License.
  18. # You may obtain a copy of the License at
  19. #
  20. # http://www.apache.org/licenses/LICENSE-2.0
  21. #
  22. # Unless required by applicable law or agreed to in writing, software
  23. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  24. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. # See the License for the specific language governing permissions and
  26. # limitations under the License.
  27. #
  28. # **********
  29. #
  30. # **********
  31. # GNU General Public License v2.0 or later:
  32. #
  33. # This program is free software; you can redistribute it and/or modify
  34. # it under the terms of the GNU General Public License as published by
  35. # the Free Software Foundation; either version 2 of the License, or
  36. # (at your option) any later version.
  37. #
  38. # This program is distributed in the hope that it will be useful,
  39. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  40. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  41. # GNU General Public License for more details.
  42. #
  43. # You should have received a copy of the GNU General Public License along
  44. # with this program; if not, write to the Free Software Foundation, Inc.,
  45. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  46. #
  47. # **********
  48. use strict;
  49. my ($include_dir, $data_dir, $error_file);
  50. if( @ARGV ) {
  51. die "Invalid number of arguments" if scalar @ARGV != 3;
  52. ($include_dir, $data_dir, $error_file) = @ARGV;
  53. -d $include_dir or die "No such directory: $include_dir\n";
  54. -d $data_dir or die "No such directory: $data_dir\n";
  55. } else {
  56. $include_dir = 'include/mbedtls';
  57. $data_dir = 'scripts/data_files';
  58. $error_file = 'library/error.c';
  59. unless( -d $include_dir && -d $data_dir ) {
  60. chdir '..' or die;
  61. -d $include_dir && -d $data_dir
  62. or die "Without arguments, must be run from root or scripts\n"
  63. }
  64. }
  65. my $error_format_file = $data_dir.'/error.fmt';
  66. my @low_level_modules = qw( AES ARC4 ARIA ASN1 BASE64 BIGNUM BLOWFISH
  67. CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES
  68. ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5
  69. NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160
  70. SHA1 SHA256 SHA512 THREADING XTEA );
  71. my @high_level_modules = qw( CIPHER DHM ECP MD
  72. PEM PK PKCS12 PKCS5
  73. RSA SSL X509 );
  74. my $line_separator = $/;
  75. undef $/;
  76. open(FORMAT_FILE, "$error_format_file") or die "Opening error format file '$error_format_file': $!";
  77. my $error_format = <FORMAT_FILE>;
  78. close(FORMAT_FILE);
  79. $/ = $line_separator;
  80. my @files = <$include_dir/*.h>;
  81. my @necessary_include_files;
  82. my @matches;
  83. foreach my $file (@files) {
  84. open(FILE, "$file");
  85. my @grep_res = grep(/^\s*#define\s+MBEDTLS_ERR_\w+\s+\-0x[0-9A-Fa-f]+/, <FILE>);
  86. push(@matches, @grep_res);
  87. close FILE;
  88. my $include_name = $file;
  89. $include_name =~ s!.*/!!;
  90. push @necessary_include_files, $include_name if @grep_res;
  91. }
  92. my $ll_old_define = "";
  93. my $hl_old_define = "";
  94. my $ll_code_check = "";
  95. my $hl_code_check = "";
  96. my $headers = "";
  97. my %included_headers;
  98. my %error_codes_seen;
  99. foreach my $line (@matches)
  100. {
  101. next if ($line =~ /compat-1.2.h/);
  102. my ($error_name, $error_code) = $line =~ /(MBEDTLS_ERR_\w+)\s+\-(0x\w+)/;
  103. my ($description) = $line =~ /\/\*\*< (.*?)\.? \*\//;
  104. die "Duplicated error code: $error_code ($error_name)\n"
  105. if( $error_codes_seen{$error_code}++ );
  106. $description =~ s/\\/\\\\/g;
  107. if ($description eq "") {
  108. $description = "DESCRIPTION MISSING";
  109. warn "Missing description for $error_name\n";
  110. }
  111. my ($module_name) = $error_name =~ /^MBEDTLS_ERR_([^_]+)/;
  112. # Fix faulty ones
  113. $module_name = "BIGNUM" if ($module_name eq "MPI");
  114. $module_name = "CTR_DRBG" if ($module_name eq "CTR");
  115. $module_name = "HMAC_DRBG" if ($module_name eq "HMAC");
  116. my $define_name = $module_name;
  117. $define_name = "X509_USE,X509_CREATE" if ($define_name eq "X509");
  118. $define_name = "ASN1_PARSE" if ($define_name eq "ASN1");
  119. $define_name = "SSL_TLS" if ($define_name eq "SSL");
  120. $define_name = "PEM_PARSE,PEM_WRITE" if ($define_name eq "PEM");
  121. my $include_name = $module_name;
  122. $include_name =~ tr/A-Z/a-z/;
  123. # Fix faulty ones
  124. $include_name = "net_sockets" if ($module_name eq "NET");
  125. $included_headers{"${include_name}.h"} = $module_name;
  126. my $found_ll = grep $_ eq $module_name, @low_level_modules;
  127. my $found_hl = grep $_ eq $module_name, @high_level_modules;
  128. if (!$found_ll && !$found_hl)
  129. {
  130. printf("Error: Do not know how to handle: $module_name\n");
  131. exit 1;
  132. }
  133. my $code_check;
  134. my $old_define;
  135. my $white_space;
  136. my $first;
  137. if ($found_ll)
  138. {
  139. $code_check = \$ll_code_check;
  140. $old_define = \$ll_old_define;
  141. $white_space = ' ';
  142. }
  143. else
  144. {
  145. $code_check = \$hl_code_check;
  146. $old_define = \$hl_old_define;
  147. $white_space = ' ';
  148. }
  149. if ($define_name ne ${$old_define})
  150. {
  151. if (${$old_define} ne "")
  152. {
  153. ${$code_check} .= "#endif /* ";
  154. $first = 0;
  155. foreach my $dep (split(/,/, ${$old_define}))
  156. {
  157. ${$code_check} .= " || " if ($first++);
  158. ${$code_check} .= "MBEDTLS_${dep}_C";
  159. }
  160. ${$code_check} .= " */\n\n";
  161. }
  162. ${$code_check} .= "#if ";
  163. $headers .= "#if " if ($include_name ne "");
  164. $first = 0;
  165. foreach my $dep (split(/,/, ${define_name}))
  166. {
  167. ${$code_check} .= " || " if ($first);
  168. $headers .= " || " if ($first++);
  169. ${$code_check} .= "defined(MBEDTLS_${dep}_C)";
  170. $headers .= "defined(MBEDTLS_${dep}_C)" if
  171. ($include_name ne "");
  172. }
  173. ${$code_check} .= "\n";
  174. $headers .= "\n#include \"mbedtls/${include_name}.h\"\n".
  175. "#endif\n\n" if ($include_name ne "");
  176. ${$old_define} = $define_name;
  177. }
  178. if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE")
  179. {
  180. ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
  181. "${white_space}\{\n".
  182. "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n".
  183. "${white_space} return;\n".
  184. "${white_space}}\n"
  185. }
  186. else
  187. {
  188. ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
  189. "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n"
  190. }
  191. };
  192. if ($ll_old_define ne "")
  193. {
  194. $ll_code_check .= "#endif /* ";
  195. my $first = 0;
  196. foreach my $dep (split(/,/, $ll_old_define))
  197. {
  198. $ll_code_check .= " || " if ($first++);
  199. $ll_code_check .= "MBEDTLS_${dep}_C";
  200. }
  201. $ll_code_check .= " */\n";
  202. }
  203. if ($hl_old_define ne "")
  204. {
  205. $hl_code_check .= "#endif /* ";
  206. my $first = 0;
  207. foreach my $dep (split(/,/, $hl_old_define))
  208. {
  209. $hl_code_check .= " || " if ($first++);
  210. $hl_code_check .= "MBEDTLS_${dep}_C";
  211. }
  212. $hl_code_check .= " */\n";
  213. }
  214. $error_format =~ s/HEADER_INCLUDED\n/$headers/g;
  215. $error_format =~ s/LOW_LEVEL_CODE_CHECKS\n/$ll_code_check/g;
  216. $error_format =~ s/HIGH_LEVEL_CODE_CHECKS\n/$hl_code_check/g;
  217. open(ERROR_FILE, ">$error_file") or die "Opening destination file '$error_file': $!";
  218. print ERROR_FILE $error_format;
  219. close(ERROR_FILE);
  220. my $errors = 0;
  221. for my $include_name (@necessary_include_files)
  222. {
  223. if (not $included_headers{$include_name})
  224. {
  225. print STDERR "The header file \"$include_name\" defines error codes but has not been included!\n";
  226. ++$errors;
  227. }
  228. }
  229. exit !!$errors;