├── .gitignore ├── LICENSE ├── README.md ├── asn ├── Makefile ├── asn1.h ├── asn1_ber_bytecode.h ├── asn1_decoder.c ├── asn1_decoder.h ├── asn1_decoder_fixed.c ├── misc.c ├── misc.h ├── oid_registry.c ├── oid_registry.h ├── oid_registry_data.c ├── oob_read_1217.x509 ├── oob_read_1396.x509 ├── oob_read_928.x509 ├── pkcs7-asn1.c ├── pkcs7-asn1.h ├── pkcs7.h ├── pkcs7_main.c ├── pkcs7_parser.c ├── pkcs7_parser.h ├── pkcs7_test.c ├── rsa.h ├── rsa_helper.c ├── rsa_main.c ├── rsaprivkey-asn1.c ├── rsaprivkey-asn1.h ├── rsapubkey-asn1.c ├── rsapubkey-asn1.h ├── x509-asn1.c ├── x509-asn1.h ├── x509_cert.h ├── x509_cert_parser.c ├── x509_inputs.tar.xz ├── x509_main.c ├── x509_rsakey-asn1.c ├── x509_rsakey-asn1.h └── x509_test.c └── bc ├── Makefile └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *.bc 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The majority of the code in this repository is derived from the Linux Kernel. As 2 | such, the code falls under the Linux Kernel's licensing terms, i.e. GPLv2. For 3 | more information, see the LICENSES/ directory within the Linux Kernel source 4 | code. 5 | 6 | 7 | GNU GENERAL PUBLIC LICENSE 8 | Version 2, June 1991 9 | 10 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 11 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 12 | Everyone is permitted to copy and distribute verbatim copies 13 | of this license document, but changing it is not allowed. 14 | 15 | Preamble 16 | 17 | The licenses for most software are designed to take away your 18 | freedom to share and change it. By contrast, the GNU General Public 19 | License is intended to guarantee your freedom to share and change free 20 | software--to make sure the software is free for all its users. This 21 | General Public License applies to most of the Free Software 22 | Foundation's software and to any other program whose authors commit to 23 | using it. (Some other Free Software Foundation software is covered by 24 | the GNU Library General Public License instead.) You can apply it to 25 | your programs, too. 26 | 27 | When we speak of free software, we are referring to freedom, not 28 | price. Our General Public Licenses are designed to make sure that you 29 | have the freedom to distribute copies of free software (and charge for 30 | this service if you wish), that you receive source code or can get it 31 | if you want it, that you can change the software or use pieces of it 32 | in new free programs; and that you know you can do these things. 33 | 34 | To protect your rights, we need to make restrictions that forbid 35 | anyone to deny you these rights or to ask you to surrender the rights. 36 | These restrictions translate to certain responsibilities for you if you 37 | distribute copies of the software, or if you modify it. 38 | 39 | For example, if you distribute copies of such a program, whether 40 | gratis or for a fee, you must give the recipients all the rights that 41 | you have. You must make sure that they, too, receive or can get the 42 | source code. And you must show them these terms so they know their 43 | rights. 44 | 45 | We protect your rights with two steps: (1) copyright the software, and 46 | (2) offer you this license which gives you legal permission to copy, 47 | distribute and/or modify the software. 48 | 49 | Also, for each author's protection and ours, we want to make certain 50 | that everyone understands that there is no warranty for this free 51 | software. If the software is modified by someone else and passed on, we 52 | want its recipients to know that what they have is not the original, so 53 | that any problems introduced by others will not reflect on the original 54 | authors' reputations. 55 | 56 | Finally, any free program is threatened constantly by software 57 | patents. We wish to avoid the danger that redistributors of a free 58 | program will individually obtain patent licenses, in effect making the 59 | program proprietary. To prevent this, we have made it clear that any 60 | patent must be licensed for everyone's free use or not licensed at all. 61 | 62 | The precise terms and conditions for copying, distribution and 63 | modification follow. 64 | 65 | GNU GENERAL PUBLIC LICENSE 66 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 67 | 68 | 0. This License applies to any program or other work which contains 69 | a notice placed by the copyright holder saying it may be distributed 70 | under the terms of this General Public License. The "Program", below, 71 | refers to any such program or work, and a "work based on the Program" 72 | means either the Program or any derivative work under copyright law: 73 | that is to say, a work containing the Program or a portion of it, 74 | either verbatim or with modifications and/or translated into another 75 | language. (Hereinafter, translation is included without limitation in 76 | the term "modification".) Each licensee is addressed as "you". 77 | 78 | Activities other than copying, distribution and modification are not 79 | covered by this License; they are outside its scope. The act of 80 | running the Program is not restricted, and the output from the Program 81 | is covered only if its contents constitute a work based on the 82 | Program (independent of having been made by running the Program). 83 | Whether that is true depends on what the Program does. 84 | 85 | 1. You may copy and distribute verbatim copies of the Program's 86 | source code as you receive it, in any medium, provided that you 87 | conspicuously and appropriately publish on each copy an appropriate 88 | copyright notice and disclaimer of warranty; keep intact all the 89 | notices that refer to this License and to the absence of any warranty; 90 | and give any other recipients of the Program a copy of this License 91 | along with the Program. 92 | 93 | You may charge a fee for the physical act of transferring a copy, and 94 | you may at your option offer warranty protection in exchange for a fee. 95 | 96 | 2. You may modify your copy or copies of the Program or any portion 97 | of it, thus forming a work based on the Program, and copy and 98 | distribute such modifications or work under the terms of Section 1 99 | above, provided that you also meet all of these conditions: 100 | 101 | a) You must cause the modified files to carry prominent notices 102 | stating that you changed the files and the date of any change. 103 | 104 | b) You must cause any work that you distribute or publish, that in 105 | whole or in part contains or is derived from the Program or any 106 | part thereof, to be licensed as a whole at no charge to all third 107 | parties under the terms of this License. 108 | 109 | c) If the modified program normally reads commands interactively 110 | when run, you must cause it, when started running for such 111 | interactive use in the most ordinary way, to print or display an 112 | announcement including an appropriate copyright notice and a 113 | notice that there is no warranty (or else, saying that you provide 114 | a warranty) and that users may redistribute the program under 115 | these conditions, and telling the user how to view a copy of this 116 | License. (Exception: if the Program itself is interactive but 117 | does not normally print such an announcement, your work based on 118 | the Program is not required to print an announcement.) 119 | 120 | These requirements apply to the modified work as a whole. If 121 | identifiable sections of that work are not derived from the Program, 122 | and can be reasonably considered independent and separate works in 123 | themselves, then this License, and its terms, do not apply to those 124 | sections when you distribute them as separate works. But when you 125 | distribute the same sections as part of a whole which is a work based 126 | on the Program, the distribution of the whole must be on the terms of 127 | this License, whose permissions for other licensees extend to the 128 | entire whole, and thus to each and every part regardless of who wrote it. 129 | 130 | Thus, it is not the intent of this section to claim rights or contest 131 | your rights to work written entirely by you; rather, the intent is to 132 | exercise the right to control the distribution of derivative or 133 | collective works based on the Program. 134 | 135 | In addition, mere aggregation of another work not based on the Program 136 | with the Program (or with a work based on the Program) on a volume of 137 | a storage or distribution medium does not bring the other work under 138 | the scope of this License. 139 | 140 | 3. You may copy and distribute the Program (or a work based on it, 141 | under Section 2) in object code or executable form under the terms of 142 | Sections 1 and 2 above provided that you also do one of the following: 143 | 144 | a) Accompany it with the complete corresponding machine-readable 145 | source code, which must be distributed under the terms of Sections 146 | 1 and 2 above on a medium customarily used for software interchange; or, 147 | 148 | b) Accompany it with a written offer, valid for at least three 149 | years, to give any third party, for a charge no more than your 150 | cost of physically performing source distribution, a complete 151 | machine-readable copy of the corresponding source code, to be 152 | distributed under the terms of Sections 1 and 2 above on a medium 153 | customarily used for software interchange; or, 154 | 155 | c) Accompany it with the information you received as to the offer 156 | to distribute corresponding source code. (This alternative is 157 | allowed only for noncommercial distribution and only if you 158 | received the program in object code or executable form with such 159 | an offer, in accord with Subsection b above.) 160 | 161 | The source code for a work means the preferred form of the work for 162 | making modifications to it. For an executable work, complete source 163 | code means all the source code for all modules it contains, plus any 164 | associated interface definition files, plus the scripts used to 165 | control compilation and installation of the executable. However, as a 166 | special exception, the source code distributed need not include 167 | anything that is normally distributed (in either source or binary 168 | form) with the major components (compiler, kernel, and so on) of the 169 | operating system on which the executable runs, unless that component 170 | itself accompanies the executable. 171 | 172 | If distribution of executable or object code is made by offering 173 | access to copy from a designated place, then offering equivalent 174 | access to copy the source code from the same place counts as 175 | distribution of the source code, even though third parties are not 176 | compelled to copy the source along with the object code. 177 | 178 | 4. You may not copy, modify, sublicense, or distribute the Program 179 | except as expressly provided under this License. Any attempt 180 | otherwise to copy, modify, sublicense or distribute the Program is 181 | void, and will automatically terminate your rights under this License. 182 | However, parties who have received copies, or rights, from you under 183 | this License will not have their licenses terminated so long as such 184 | parties remain in full compliance. 185 | 186 | 5. You are not required to accept this License, since you have not 187 | signed it. However, nothing else grants you permission to modify or 188 | distribute the Program or its derivative works. These actions are 189 | prohibited by law if you do not accept this License. Therefore, by 190 | modifying or distributing the Program (or any work based on the 191 | Program), you indicate your acceptance of this License to do so, and 192 | all its terms and conditions for copying, distributing or modifying 193 | the Program or works based on it. 194 | 195 | 6. Each time you redistribute the Program (or any work based on the 196 | Program), the recipient automatically receives a license from the 197 | original licensor to copy, distribute or modify the Program subject to 198 | these terms and conditions. You may not impose any further 199 | restrictions on the recipients' exercise of the rights granted herein. 200 | You are not responsible for enforcing compliance by third parties to 201 | this License. 202 | 203 | 7. If, as a consequence of a court judgment or allegation of patent 204 | infringement or for any other reason (not limited to patent issues), 205 | conditions are imposed on you (whether by court order, agreement or 206 | otherwise) that contradict the conditions of this License, they do not 207 | excuse you from the conditions of this License. If you cannot 208 | distribute so as to satisfy simultaneously your obligations under this 209 | License and any other pertinent obligations, then as a consequence you 210 | may not distribute the Program at all. For example, if a patent 211 | license would not permit royalty-free redistribution of the Program by 212 | all those who receive copies directly or indirectly through you, then 213 | the only way you could satisfy both it and this License would be to 214 | refrain entirely from distribution of the Program. 215 | 216 | If any portion of this section is held invalid or unenforceable under 217 | any particular circumstance, the balance of the section is intended to 218 | apply and the section as a whole is intended to apply in other 219 | circumstances. 220 | 221 | It is not the purpose of this section to induce you to infringe any 222 | patents or other property right claims or to contest validity of any 223 | such claims; this section has the sole purpose of protecting the 224 | integrity of the free software distribution system, which is 225 | implemented by public license practices. Many people have made 226 | generous contributions to the wide range of software distributed 227 | through that system in reliance on consistent application of that 228 | system; it is up to the author/donor to decide if he or she is willing 229 | to distribute software through any other system and a licensee cannot 230 | impose that choice. 231 | 232 | This section is intended to make thoroughly clear what is believed to 233 | be a consequence of the rest of this License. 234 | 235 | 8. If the distribution and/or use of the Program is restricted in 236 | certain countries either by patents or by copyrighted interfaces, the 237 | original copyright holder who places the Program under this License 238 | may add an explicit geographical distribution limitation excluding 239 | those countries, so that distribution is permitted only in or among 240 | countries not thus excluded. In such case, this License incorporates 241 | the limitation as if written in the body of this License. 242 | 243 | 9. The Free Software Foundation may publish revised and/or new versions 244 | of the General Public License from time to time. Such new versions will 245 | be similar in spirit to the present version, but may differ in detail to 246 | address new problems or concerns. 247 | 248 | Each version is given a distinguishing version number. If the Program 249 | specifies a version number of this License which applies to it and "any 250 | later version", you have the option of following the terms and conditions 251 | either of that version or of any later version published by the Free 252 | Software Foundation. If the Program does not specify a version number of 253 | this License, you may choose any version ever published by the Free Software 254 | Foundation. 255 | 256 | 10. If you wish to incorporate parts of the Program into other free 257 | programs whose distribution conditions are different, write to the author 258 | to ask for permission. For software which is copyrighted by the Free 259 | Software Foundation, write to the Free Software Foundation; we sometimes 260 | make exceptions for this. Our decision will be guided by the two goals 261 | of preserving the free status of all derivatives of our free software and 262 | of promoting the sharing and reuse of software generally. 263 | 264 | NO WARRANTY 265 | 266 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 267 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 268 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 269 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 270 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 271 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 272 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 273 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 274 | REPAIR OR CORRECTION. 275 | 276 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 277 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 278 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 279 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 280 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 281 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 282 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 283 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 284 | POSSIBILITY OF SUCH DAMAGES. 285 | 286 | END OF TERMS AND CONDITIONS 287 | 288 | How to Apply These Terms to Your New Programs 289 | 290 | If you develop a new program, and you want it to be of the greatest 291 | possible use to the public, the best way to achieve this is to make it 292 | free software which everyone can redistribute and change under these terms. 293 | 294 | To do so, attach the following notices to the program. It is safest 295 | to attach them to the start of each source file to most effectively 296 | convey the exclusion of warranty; and each file should have at least 297 | the "copyright" line and a pointer to where the full notice is found. 298 | 299 | 300 | Copyright (C) 301 | 302 | This program is free software; you can redistribute it and/or modify 303 | it under the terms of the GNU General Public License as published by 304 | the Free Software Foundation; either version 2 of the License, or 305 | (at your option) any later version. 306 | 307 | This program is distributed in the hope that it will be useful, 308 | but WITHOUT ANY WARRANTY; without even the implied warranty of 309 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 310 | GNU General Public License for more details. 311 | 312 | You should have received a copy of the GNU General Public License 313 | along with this program; if not, write to the Free Software 314 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 315 | 316 | 317 | Also add information on how to contact you by electronic and paper mail. 318 | 319 | If the program is interactive, make it output a short notice like this 320 | when it starts in an interactive mode: 321 | 322 | Gnomovision version 69, Copyright (C) year name of author 323 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 324 | This is free software, and you are welcome to redistribute it 325 | under certain conditions; type `show c' for details. 326 | 327 | The hypothetical commands `show w' and `show c' should show the appropriate 328 | parts of the General Public License. Of course, the commands you use may 329 | be called something other than `show w' and `show c'; they could even be 330 | mouse-clicks or menu items--whatever suits your program. 331 | 332 | You should also get your employer (if you work as a programmer) or your 333 | school, if any, to sign a "copyright disclaimer" for the program, if 334 | necessary. Here is a sample; alter the names: 335 | 336 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 337 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 338 | 339 | , 1 April 1989 340 | Ty Coon, President of Vice 341 | 342 | This General Public License does not permit incorporating your program into 343 | proprietary programs. If your program is a subroutine library, you may 344 | consider it more useful to permit linking proprietary applications with the 345 | library. If this is what you want to do, use the GNU Library General 346 | Public License instead of this License. 347 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains code extracted from the Linux kernel and modified to 2 | run in userland. This enables security tools which can only handle userland 3 | programs to be used on the code. 4 | 5 | The material here will make a lot more sense after reading the blog post 6 | which goes with it. 7 | https://blog.grimm-co.com/post/analyzing-the-linux-kernel-in-userland-with-afl-and-klee/ 8 | -------------------------------------------------------------------------------- /asn/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: x509 pkcs7 rsa x509_debug pkcs7_debug rsa_debug x509_klee_debug pkcs7_klee_debug rsa_klee_debug 3 | 4 | X509_SRC=misc.c oid_registry.c asn1_decoder.c x509-asn1.c x509_rsakey-asn1.c x509_cert_parser.c x509_main.c 5 | X509_FIXED_SRC=misc.c oid_registry.c asn1_decoder_fixed.c x509-asn1.c x509_rsakey-asn1.c x509_cert_parser.c x509_main.c 6 | PKCS7_SRC=misc.c oid_registry.c asn1_decoder.c pkcs7-asn1.c pkcs7_parser.c x509_cert_parser.c x509-asn1.c x509_rsakey-asn1.c pkcs7_main.c 7 | RSA_SRC=misc.c oid_registry.c asn1_decoder.c rsapubkey-asn1.c rsaprivkey-asn1.c rsa_helper.c rsa_main.c 8 | 9 | x509: 10 | $(CC) $(CFLAGS) $(X509_SRC) -o x509 11 | 12 | x509_debug: 13 | $(CC) -g -O0 -DDEBUG $(CFLAGS) $(X509_SRC) -o x509_debug 14 | 15 | x509_debug_fixed: 16 | $(CC) -g -O0 -DDEBUG $(CFLAGS) $(X509_FIXED_SRC) -o x509_debug_fixed 17 | 18 | x509_klee_debug: 19 | $(CC) -g -O0 -DDEBUG -DKLEE_DEBUG $(CFLAGS) $(X509_SRC) -o x509_klee_debug 20 | 21 | x509_klee: 22 | cat $(X509_SRC) > x509_klee.c 23 | clang -I klee_src/include/ -DKLEE -emit-llvm -g -c -O0 -Xclang -disable-O0-optnone x509_klee.c -o x509_klee.bc 24 | 25 | x509_test: 26 | $(CC) -g -O0 -DDEBUG $(CFLAGS) x509_test.c -o x509_test 27 | 28 | pkcs7: 29 | $(CC) $(CFLAGS) $(PKCS7_SRC) -o pkcs7 30 | 31 | pkcs7_debug: 32 | $(CC) -g -O0 -DDEBUG $(CFLAGS) $(PKCS7_SRC) -o pkcs7_debug 33 | 34 | pkcs7_klee_debug: 35 | $(CC) -g -O0 -DDEBUG -DKLEE_DEBUG $(CFLAGS) $(PKCS7_SRC) -o pkcs7_klee_debug 36 | 37 | pkcs7_klee: 38 | cat $(PKCS7_SRC) > pkcs7_klee.c 39 | clang -I klee_src/include/ -DKLEE -emit-llvm -g -c -O0 -Xclang -disable-O0-optnone pkcs7_klee.c -o pkcs7_klee.bc 40 | 41 | pkcs7_test: 42 | $(CC) -g -O0 -DDEBUG $(CFLAGS) pkcs7_test.c -o pkcs7_test 43 | 44 | rsa: 45 | $(CC) $(CFLAGS) $(RSA_SRC) -o rsa_pub -DRSA_PUB_KEY 46 | $(CC) $(CFLAGS) $(RSA_SRC) -o rsa_priv 47 | 48 | rsa_debug: 49 | $(CC) -g -O0 -DDEBUG $(CFLAGS) $(RSA_SRC) -o rsa_pub_debug -DRSA_PUB_KEY 50 | $(CC) -g -O0 -DDEBUG $(CFLAGS) $(RSA_SRC) -o rsa_priv_debug 51 | 52 | rsa_klee_debug: 53 | $(CC) -g -O0 -DDEBUG -DKLEE_DEBUG $(CFLAGS) $(RSA_SRC) -o rsa_pub_klee_debug -DRSA_PUB_KEY 54 | $(CC) -g -O0 -DDEBUG -DKLEE_DEBUG $(CFLAGS) $(RSA_SRC) -o rsa_priv_klee_debug 55 | 56 | rsa_klee: 57 | cat $(RSA_SRC) > rsa_klee.c 58 | clang -I klee_src/include/ -DKLEE -emit-llvm -g -c -O0 -Xclang -disable-O0-optnone rsa_klee.c -o rsa_klee_pub.bc -DRSA_PUB_KEY 59 | clang -I klee_src/include/ -DKLEE -emit-llvm -g -c -O0 -Xclang -disable-O0-optnone rsa_klee.c -o rsa_klee_priv.bc 60 | 61 | clean: 62 | rm -f *.o *.bc 63 | rm -f x509 x509_debug x509_klee_debug x509_test x509_klee.c 64 | rm -f pkcs7 pkcs7_debug pkcs7_klee_debug pkcs7_test pkcs7_klee.c 65 | rm -f rsa_klee.c rsa_klee_priv.c rsa_pub rsa_priv rsa_pub_debug rsa_priv_debug rsa_pub_klee_debug rsa_priv_klee_debug 66 | 67 | .PHONY: x509 x509_debug x509_klee x509_klee_debug pkcs7 pkcs7_debug pkcs7_klee pkcs7_klee_debug rsa rsa_debug rsa_klee rsa_klee_debug 68 | -------------------------------------------------------------------------------- /asn/asn1.h: -------------------------------------------------------------------------------- 1 | /* ASN.1 BER/DER/CER encoding definitions 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef _LINUX_ASN1_H 13 | #define _LINUX_ASN1_H 14 | 15 | /* Class */ 16 | enum asn1_class { 17 | ASN1_UNIV = 0, /* Universal */ 18 | ASN1_APPL = 1, /* Application */ 19 | ASN1_CONT = 2, /* Context */ 20 | ASN1_PRIV = 3 /* Private */ 21 | }; 22 | #define ASN1_CLASS_BITS 0xc0 23 | 24 | 25 | enum asn1_method { 26 | ASN1_PRIM = 0, /* Primitive */ 27 | ASN1_CONS = 1 /* Constructed */ 28 | }; 29 | #define ASN1_CONS_BIT 0x20 30 | 31 | /* Tag */ 32 | enum asn1_tag { 33 | ASN1_EOC = 0, /* End Of Contents or N/A */ 34 | ASN1_BOOL = 1, /* Boolean */ 35 | ASN1_INT = 2, /* Integer */ 36 | ASN1_BTS = 3, /* Bit String */ 37 | ASN1_OTS = 4, /* Octet String */ 38 | ASN1_NULL = 5, /* Null */ 39 | ASN1_OID = 6, /* Object Identifier */ 40 | ASN1_ODE = 7, /* Object Description */ 41 | ASN1_EXT = 8, /* External */ 42 | ASN1_REAL = 9, /* Real float */ 43 | ASN1_ENUM = 10, /* Enumerated */ 44 | ASN1_EPDV = 11, /* Embedded PDV */ 45 | ASN1_UTF8STR = 12, /* UTF8 String */ 46 | ASN1_RELOID = 13, /* Relative OID */ 47 | /* 14 - Reserved */ 48 | /* 15 - Reserved */ 49 | ASN1_SEQ = 16, /* Sequence and Sequence of */ 50 | ASN1_SET = 17, /* Set and Set of */ 51 | ASN1_NUMSTR = 18, /* Numerical String */ 52 | ASN1_PRNSTR = 19, /* Printable String */ 53 | ASN1_TEXSTR = 20, /* T61 String / Teletext String */ 54 | ASN1_VIDSTR = 21, /* Videotex String */ 55 | ASN1_IA5STR = 22, /* IA5 String */ 56 | ASN1_UNITIM = 23, /* Universal Time */ 57 | ASN1_GENTIM = 24, /* General Time */ 58 | ASN1_GRASTR = 25, /* Graphic String */ 59 | ASN1_VISSTR = 26, /* Visible String */ 60 | ASN1_GENSTR = 27, /* General String */ 61 | ASN1_UNISTR = 28, /* Universal String */ 62 | ASN1_CHRSTR = 29, /* Character String */ 63 | ASN1_BMPSTR = 30, /* BMP String */ 64 | ASN1_LONG_TAG = 31 /* Long form tag */ 65 | }; 66 | 67 | #define ASN1_INDEFINITE_LENGTH 0x80 68 | 69 | #endif /* _LINUX_ASN1_H */ 70 | -------------------------------------------------------------------------------- /asn/asn1_ber_bytecode.h: -------------------------------------------------------------------------------- 1 | /* ASN.1 BER/DER/CER parsing state machine internal definitions 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef _LINUX_ASN1_BER_BYTECODE_H 13 | #define _LINUX_ASN1_BER_BYTECODE_H 14 | 15 | #include 16 | #include "asn1.h" 17 | 18 | typedef int (*asn1_action_t)(void *context, 19 | size_t hdrlen, /* In case of ANY type */ 20 | unsigned char tag, /* In case of ANY type */ 21 | const void *value, size_t vlen); 22 | 23 | struct asn1_decoder { 24 | const unsigned char *machine; 25 | size_t machlen; 26 | const asn1_action_t *actions; 27 | }; 28 | 29 | enum asn1_opcode { 30 | /* The tag-matching ops come first and the odd-numbered slots 31 | * are for OR_SKIP ops. 32 | */ 33 | #define ASN1_OP_MATCH__SKIP 0x01 34 | #define ASN1_OP_MATCH__ACT 0x02 35 | #define ASN1_OP_MATCH__JUMP 0x04 36 | #define ASN1_OP_MATCH__ANY 0x08 37 | #define ASN1_OP_MATCH__COND 0x10 38 | 39 | ASN1_OP_MATCH = 0x00, 40 | ASN1_OP_MATCH_OR_SKIP = 0x01, 41 | ASN1_OP_MATCH_ACT = 0x02, 42 | ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, 43 | ASN1_OP_MATCH_JUMP = 0x04, 44 | ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, 45 | ASN1_OP_MATCH_ANY = 0x08, 46 | ASN1_OP_MATCH_ANY_OR_SKIP = 0x09, 47 | ASN1_OP_MATCH_ANY_ACT = 0x0a, 48 | ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b, 49 | /* Everything before here matches unconditionally */ 50 | 51 | ASN1_OP_COND_MATCH_OR_SKIP = 0x11, 52 | ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, 53 | ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, 54 | ASN1_OP_COND_MATCH_ANY = 0x18, 55 | ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19, 56 | ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, 57 | ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b, 58 | 59 | /* Everything before here will want a tag from the data */ 60 | #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP 61 | 62 | /* These are here to help fill up space */ 63 | ASN1_OP_COND_FAIL = 0x1c, 64 | ASN1_OP_COMPLETE = 0x1d, 65 | ASN1_OP_ACT = 0x1e, 66 | ASN1_OP_MAYBE_ACT = 0x1f, 67 | 68 | /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ 69 | ASN1_OP_END_SEQ = 0x20, 70 | ASN1_OP_END_SET = 0x21, 71 | ASN1_OP_END_SEQ_OF = 0x22, 72 | ASN1_OP_END_SET_OF = 0x23, 73 | ASN1_OP_END_SEQ_ACT = 0x24, 74 | ASN1_OP_END_SET_ACT = 0x25, 75 | ASN1_OP_END_SEQ_OF_ACT = 0x26, 76 | ASN1_OP_END_SET_OF_ACT = 0x27, 77 | #define ASN1_OP_END__SET 0x01 78 | #define ASN1_OP_END__OF 0x02 79 | #define ASN1_OP_END__ACT 0x04 80 | 81 | ASN1_OP_RETURN = 0x28, 82 | 83 | ASN1_OP__NR 84 | }; 85 | 86 | #define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) 87 | #define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) 88 | #define _jump_target(N) (N) 89 | #define _action(N) (N) 90 | 91 | #endif /* _LINUX_ASN1_BER_BYTECODE_H */ 92 | -------------------------------------------------------------------------------- /asn/asn1_decoder.c: -------------------------------------------------------------------------------- 1 | /* Decoder for ASN.1 BER/DER/CER encoded bytestream 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "asn1_decoder.h" 16 | #include "asn1_ber_bytecode.h" 17 | #include "misc.h" 18 | 19 | static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { 20 | /* OPC TAG JMP ACT */ 21 | [ASN1_OP_MATCH] = 1 + 1, 22 | [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, 23 | [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, 24 | [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, 25 | [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, 26 | [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 27 | [ASN1_OP_MATCH_ANY] = 1, 28 | [ASN1_OP_MATCH_ANY_OR_SKIP] = 1, 29 | [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, 30 | [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, 31 | [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, 32 | [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, 33 | [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 34 | [ASN1_OP_COND_MATCH_ANY] = 1, 35 | [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1, 36 | [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, 37 | [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, 38 | [ASN1_OP_COND_FAIL] = 1, 39 | [ASN1_OP_COMPLETE] = 1, 40 | [ASN1_OP_ACT] = 1 + 1, 41 | [ASN1_OP_MAYBE_ACT] = 1 + 1, 42 | [ASN1_OP_RETURN] = 1, 43 | [ASN1_OP_END_SEQ] = 1, 44 | [ASN1_OP_END_SEQ_OF] = 1 + 1, 45 | [ASN1_OP_END_SET] = 1, 46 | [ASN1_OP_END_SET_OF] = 1 + 1, 47 | [ASN1_OP_END_SEQ_ACT] = 1 + 1, 48 | [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, 49 | [ASN1_OP_END_SET_ACT] = 1 + 1, 50 | [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, 51 | }; 52 | 53 | /* 54 | * Find the length of an indefinite length object 55 | * @data: The data buffer 56 | * @datalen: The end of the innermost containing element in the buffer 57 | * @_dp: The data parse cursor (updated before returning) 58 | * @_len: Where to return the size of the element. 59 | * @_errmsg: Where to return a pointer to an error message on error 60 | */ 61 | static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, 62 | size_t *_dp, size_t *_len, 63 | const char **_errmsg) 64 | { 65 | unsigned char tag, tmp; 66 | size_t dp = *_dp, len, n; 67 | int indef_level = 1; 68 | 69 | next_tag: 70 | if (unlikely(datalen - dp < 2)) { 71 | if (datalen == dp) 72 | goto missing_eoc; 73 | goto data_overrun_error; 74 | } 75 | 76 | /* Extract a tag from the data */ 77 | tag = data[dp++]; 78 | if (tag == ASN1_EOC) { 79 | /* It appears to be an EOC. */ 80 | if (data[dp++] != 0) 81 | goto invalid_eoc; 82 | if (--indef_level <= 0) { 83 | *_len = dp - *_dp; 84 | *_dp = dp; 85 | return 0; 86 | } 87 | goto next_tag; 88 | } 89 | 90 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) { 91 | do { 92 | if (unlikely(datalen - dp < 2)) 93 | goto data_overrun_error; 94 | tmp = data[dp++]; 95 | } while (tmp & 0x80); 96 | } 97 | 98 | /* Extract the length */ 99 | len = data[dp++]; 100 | if (len <= 0x7f) 101 | goto check_length; 102 | 103 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { 104 | /* Indefinite length */ 105 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) 106 | goto indefinite_len_primitive; 107 | indef_level++; 108 | goto next_tag; 109 | } 110 | 111 | n = len - 0x80; 112 | if (unlikely(n > sizeof(len) - 1)) 113 | goto length_too_long; 114 | if (unlikely(n > datalen - dp)) 115 | goto data_overrun_error; 116 | len = 0; 117 | for (; n > 0; n--) { 118 | len <<= 8; 119 | len |= data[dp++]; 120 | } 121 | check_length: 122 | if (len > datalen - dp) 123 | goto data_overrun_error; 124 | dp += len; 125 | goto next_tag; 126 | 127 | length_too_long: 128 | *_errmsg = "Unsupported length (in asn1_find_indefinite_length)"; 129 | goto error; 130 | indefinite_len_primitive: 131 | *_errmsg = "Indefinite len primitive not permitted (in asn1_find_indefinite_length)"; 132 | goto error; 133 | invalid_eoc: 134 | *_errmsg = "Invalid length EOC (in asn1_find_indefinite_length)"; 135 | goto error; 136 | data_overrun_error: 137 | *_errmsg = "Data overrun error (in asn1_find_indefinite_length)"; 138 | goto error; 139 | missing_eoc: 140 | *_errmsg = "Missing EOC in indefinite len cons"; 141 | error: 142 | *_dp = dp; 143 | return -1; 144 | } 145 | 146 | /** 147 | * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern 148 | * @decoder: The decoder definition (produced by asn1_compiler) 149 | * @context: The caller's context (to be passed to the action functions) 150 | * @data: The encoded data 151 | * @datasize: The size of the encoded data 152 | * 153 | * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern 154 | * produced by asn1_compiler. Action functions are called on marked tags to 155 | * allow the caller to retrieve significant data. 156 | * 157 | * LIMITATIONS: 158 | * 159 | * To keep down the amount of stack used by this function, the following limits 160 | * have been imposed: 161 | * 162 | * (1) This won't handle datalen > 65535 without increasing the size of the 163 | * cons stack elements and length_too_long checking. 164 | * 165 | * (2) The stack of constructed types is 10 deep. If the depth of non-leaf 166 | * constructed types exceeds this, the decode will fail. 167 | * 168 | * (3) The SET type (not the SET OF type) isn't really supported as tracking 169 | * what members of the set have been seen is a pain. 170 | */ 171 | int asn1_ber_decoder(const struct asn1_decoder *decoder, 172 | void *context, 173 | const unsigned char *data, 174 | size_t datalen) 175 | { 176 | const unsigned char *machine = decoder->machine; 177 | const asn1_action_t *actions = decoder->actions; 178 | size_t machlen = decoder->machlen; 179 | enum asn1_opcode op; 180 | unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; 181 | const char *errmsg; 182 | size_t pc = 0, dp = 0, tdp = 0, len = 0; 183 | int ret; 184 | 185 | unsigned char flags = 0; 186 | #define FLAG_INDEFINITE_LENGTH 0x01 187 | #define FLAG_MATCHED 0x02 188 | #define FLAG_LAST_MATCHED 0x04 /* Last tag matched */ 189 | #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag 190 | * - ie. whether or not we are going to parse 191 | * a compound type. 192 | */ 193 | 194 | #define NR_CONS_STACK 10 195 | unsigned short cons_dp_stack[NR_CONS_STACK]; 196 | unsigned short cons_datalen_stack[NR_CONS_STACK]; 197 | unsigned char cons_hdrlen_stack[NR_CONS_STACK]; 198 | #define NR_JUMP_STACK 10 199 | unsigned char jump_stack[NR_JUMP_STACK]; 200 | 201 | if (datalen > 65535) 202 | return -EMSGSIZE; 203 | 204 | next_op: 205 | pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", 206 | pc, machlen, dp, datalen, csp, jsp); 207 | if (unlikely(pc >= machlen)) 208 | goto machine_overrun_error; 209 | op = machine[pc]; 210 | if (unlikely(pc + asn1_op_lengths[op] > machlen)) 211 | goto machine_overrun_error; 212 | 213 | /* If this command is meant to match a tag, then do that before 214 | * evaluating the command. 215 | */ 216 | if (op <= ASN1_OP__MATCHES_TAG) { 217 | unsigned char tmp; 218 | 219 | /* Skip conditional matches if possible */ 220 | if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || 221 | (op & ASN1_OP_MATCH__SKIP && dp == datalen)) { 222 | flags &= ~FLAG_LAST_MATCHED; 223 | pc += asn1_op_lengths[op]; 224 | goto next_op; 225 | } 226 | 227 | flags = 0; 228 | hdr = 2; 229 | 230 | /* Extract a tag from the data */ 231 | if (unlikely(dp >= datalen - 1)) { 232 | pr_debug("dp >= datalen - 1 - dp %lu datalen %lu\n", dp, datalen); 233 | goto data_overrun_error; 234 | } 235 | tag = data[dp++]; 236 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) 237 | goto long_tag_not_supported; 238 | 239 | if (op & ASN1_OP_MATCH__ANY) { 240 | pr_debug("- any %02x\n", tag); 241 | } else { 242 | /* Extract the tag from the machine 243 | * - Either CONS or PRIM are permitted in the data if 244 | * CONS is not set in the op stream, otherwise CONS 245 | * is mandatory. 246 | */ 247 | optag = machine[pc + 1]; 248 | flags |= optag & FLAG_CONS; 249 | 250 | /* Determine whether the tag matched */ 251 | tmp = optag ^ tag; 252 | tmp &= ~(optag & ASN1_CONS_BIT); 253 | pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); 254 | if (tmp != 0) { 255 | /* All odd-numbered tags are MATCH_OR_SKIP. */ 256 | if (op & ASN1_OP_MATCH__SKIP) { 257 | pc += asn1_op_lengths[op]; 258 | dp--; 259 | goto next_op; 260 | } 261 | goto tag_mismatch; 262 | } 263 | } 264 | flags |= FLAG_MATCHED; 265 | 266 | len = data[dp++]; 267 | if (len > 0x7f) { 268 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { 269 | /* Indefinite length */ 270 | if (unlikely(!(tag & ASN1_CONS_BIT))) 271 | goto indefinite_len_primitive; 272 | flags |= FLAG_INDEFINITE_LENGTH; 273 | if (unlikely(2 > datalen - dp)) 274 | goto data_overrun_error; 275 | } else { 276 | int n = len - 0x80; 277 | if (unlikely(n > 2)) 278 | goto length_too_long; 279 | if (unlikely(dp >= datalen - n)) 280 | goto data_overrun_error; 281 | hdr += n; 282 | for (len = 0; n > 0; n--) { 283 | len <<= 8; 284 | len |= data[dp++]; 285 | } 286 | if (unlikely(len > datalen - dp)) 287 | goto data_overrun_error; 288 | } 289 | } 290 | 291 | if (flags & FLAG_CONS) { 292 | /* For expected compound forms, we stack the positions 293 | * of the start and end of the data. 294 | */ 295 | if (unlikely(csp >= NR_CONS_STACK)) 296 | goto cons_stack_overflow; 297 | cons_dp_stack[csp] = dp; 298 | cons_hdrlen_stack[csp] = hdr; 299 | if (!(flags & FLAG_INDEFINITE_LENGTH)) { 300 | cons_datalen_stack[csp] = datalen; 301 | datalen = dp + len; 302 | } else { 303 | cons_datalen_stack[csp] = 0; 304 | } 305 | csp++; 306 | } 307 | 308 | pr_debug("- TAG: %02x %zu%s\n", 309 | tag, len, flags & FLAG_CONS ? " CONS" : ""); 310 | tdp = dp; 311 | } 312 | 313 | /* Decide how to handle the operation */ 314 | switch (op) { 315 | case ASN1_OP_MATCH_ANY_ACT: 316 | case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: 317 | case ASN1_OP_COND_MATCH_ANY_ACT: 318 | case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: 319 | ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); 320 | if (ret < 0) 321 | return ret; 322 | goto skip_data; 323 | 324 | case ASN1_OP_MATCH_ACT: 325 | case ASN1_OP_MATCH_ACT_OR_SKIP: 326 | case ASN1_OP_COND_MATCH_ACT_OR_SKIP: 327 | ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); 328 | if (ret < 0) 329 | return ret; 330 | goto skip_data; 331 | 332 | case ASN1_OP_MATCH: 333 | case ASN1_OP_MATCH_OR_SKIP: 334 | case ASN1_OP_MATCH_ANY: 335 | case ASN1_OP_MATCH_ANY_OR_SKIP: 336 | case ASN1_OP_COND_MATCH_OR_SKIP: 337 | case ASN1_OP_COND_MATCH_ANY: 338 | case ASN1_OP_COND_MATCH_ANY_OR_SKIP: 339 | skip_data: 340 | if (!(flags & FLAG_CONS)) { 341 | if (flags & FLAG_INDEFINITE_LENGTH) { 342 | ret = asn1_find_indefinite_length( 343 | data, datalen, &dp, &len, &errmsg); 344 | if (ret < 0) 345 | goto error; 346 | } else { 347 | dp += len; 348 | } 349 | pr_debug("- LEAF: %zu\n", len); 350 | } 351 | pc += asn1_op_lengths[op]; 352 | goto next_op; 353 | 354 | case ASN1_OP_MATCH_JUMP: 355 | case ASN1_OP_MATCH_JUMP_OR_SKIP: 356 | case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: 357 | pr_debug("- MATCH_JUMP\n"); 358 | if (unlikely(jsp == NR_JUMP_STACK)) 359 | goto jump_stack_overflow; 360 | jump_stack[jsp++] = pc + asn1_op_lengths[op]; 361 | pc = machine[pc + 2]; 362 | goto next_op; 363 | 364 | case ASN1_OP_COND_FAIL: 365 | if (unlikely(!(flags & FLAG_MATCHED))) 366 | goto tag_mismatch; 367 | pc += asn1_op_lengths[op]; 368 | goto next_op; 369 | 370 | case ASN1_OP_COMPLETE: 371 | if (unlikely(jsp != 0 || csp != 0)) { 372 | pr_err("ERROR: ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", 373 | jsp, csp); 374 | return -EBADMSG; 375 | } 376 | return 0; 377 | 378 | case ASN1_OP_END_SET: 379 | case ASN1_OP_END_SET_ACT: 380 | if (unlikely(!(flags & FLAG_MATCHED))) 381 | goto tag_mismatch; 382 | case ASN1_OP_END_SEQ: 383 | case ASN1_OP_END_SET_OF: 384 | case ASN1_OP_END_SEQ_OF: 385 | case ASN1_OP_END_SEQ_ACT: 386 | case ASN1_OP_END_SET_OF_ACT: 387 | case ASN1_OP_END_SEQ_OF_ACT: 388 | if (unlikely(csp <= 0)) 389 | goto cons_stack_underflow; 390 | csp--; 391 | tdp = cons_dp_stack[csp]; 392 | hdr = cons_hdrlen_stack[csp]; 393 | len = datalen; 394 | datalen = cons_datalen_stack[csp]; 395 | pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", 396 | tdp, dp, len, datalen); 397 | if (datalen == 0) { 398 | /* Indefinite length - check for the EOC. */ 399 | datalen = len; 400 | if (unlikely(datalen - dp < 2)) 401 | goto data_overrun_error; 402 | if (data[dp++] != 0) { 403 | if (op & ASN1_OP_END__OF) { 404 | dp--; 405 | csp++; 406 | pc = machine[pc + 1]; 407 | pr_debug("- continue\n"); 408 | goto next_op; 409 | } 410 | goto missing_eoc; 411 | } 412 | if (data[dp++] != 0) 413 | goto invalid_eoc; 414 | len = dp - tdp - 2; 415 | } else { 416 | if (dp < len && (op & ASN1_OP_END__OF)) { 417 | datalen = len; 418 | csp++; 419 | pc = machine[pc + 1]; 420 | pr_debug("- continue\n"); 421 | goto next_op; 422 | } 423 | if (dp != len) 424 | goto cons_length_error; 425 | len -= tdp; 426 | pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); 427 | } 428 | 429 | if (op & ASN1_OP_END__ACT) { 430 | unsigned char act; 431 | if (op & ASN1_OP_END__OF) 432 | act = machine[pc + 2]; 433 | else 434 | act = machine[pc + 1]; 435 | ret = actions[act](context, hdr, 0, data + tdp, len); 436 | } 437 | pc += asn1_op_lengths[op]; 438 | goto next_op; 439 | 440 | case ASN1_OP_MAYBE_ACT: 441 | if (!(flags & FLAG_LAST_MATCHED)) { 442 | pc += asn1_op_lengths[op]; 443 | goto next_op; 444 | } 445 | case ASN1_OP_ACT: 446 | ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); 447 | if (ret < 0) 448 | return ret; 449 | pc += asn1_op_lengths[op]; 450 | goto next_op; 451 | 452 | case ASN1_OP_RETURN: 453 | if (unlikely(jsp <= 0)) 454 | goto jump_stack_underflow; 455 | pc = jump_stack[--jsp]; 456 | flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; 457 | goto next_op; 458 | 459 | default: 460 | break; 461 | } 462 | 463 | /* Shouldn't reach here */ 464 | pr_err("ERROR: ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n", 465 | op, pc); 466 | return -EBADMSG; 467 | 468 | data_overrun_error: 469 | errmsg = "Data overrun error"; 470 | goto error; 471 | machine_overrun_error: 472 | errmsg = "Machine overrun error"; 473 | goto error; 474 | jump_stack_underflow: 475 | errmsg = "Jump stack underflow"; 476 | goto error; 477 | jump_stack_overflow: 478 | errmsg = "Jump stack overflow"; 479 | goto error; 480 | cons_stack_underflow: 481 | errmsg = "Cons stack underflow"; 482 | goto error; 483 | cons_stack_overflow: 484 | errmsg = "Cons stack overflow"; 485 | goto error; 486 | cons_length_error: 487 | errmsg = "Cons length error"; 488 | goto error; 489 | missing_eoc: 490 | errmsg = "Missing EOC in indefinite len cons"; 491 | goto error; 492 | invalid_eoc: 493 | errmsg = "Invalid length EOC"; 494 | goto error; 495 | length_too_long: 496 | errmsg = "Unsupported length"; 497 | goto error; 498 | indefinite_len_primitive: 499 | errmsg = "Indefinite len primitive not permitted"; 500 | goto error; 501 | tag_mismatch: 502 | errmsg = "Unexpected tag"; 503 | goto error; 504 | long_tag_not_supported: 505 | errmsg = "Long tag not supported"; 506 | error: 507 | pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", 508 | errmsg, pc, dp, optag, tag, len); 509 | return -EBADMSG; 510 | } 511 | -------------------------------------------------------------------------------- /asn/asn1_decoder.h: -------------------------------------------------------------------------------- 1 | /* ASN.1 decoder 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef _LINUX_ASN1_DECODER_H 13 | #define _LINUX_ASN1_DECODER_H 14 | 15 | #include "asn1.h" 16 | #include 17 | 18 | struct asn1_decoder; 19 | 20 | extern int asn1_ber_decoder(const struct asn1_decoder *decoder, 21 | void *context, 22 | const unsigned char *data, 23 | size_t datalen); 24 | 25 | #endif /* _LINUX_ASN1_DECODER_H */ 26 | -------------------------------------------------------------------------------- /asn/asn1_decoder_fixed.c: -------------------------------------------------------------------------------- 1 | /* Decoder for ASN.1 BER/DER/CER encoded bytestream 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "asn1_decoder.h" 16 | #include "asn1_ber_bytecode.h" 17 | #include "misc.h" 18 | 19 | static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { 20 | /* OPC TAG JMP ACT */ 21 | [ASN1_OP_MATCH] = 1 + 1, 22 | [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, 23 | [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, 24 | [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, 25 | [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, 26 | [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 27 | [ASN1_OP_MATCH_ANY] = 1, 28 | [ASN1_OP_MATCH_ANY_OR_SKIP] = 1, 29 | [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, 30 | [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, 31 | [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, 32 | [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, 33 | [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 34 | [ASN1_OP_COND_MATCH_ANY] = 1, 35 | [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1, 36 | [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, 37 | [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, 38 | [ASN1_OP_COND_FAIL] = 1, 39 | [ASN1_OP_COMPLETE] = 1, 40 | [ASN1_OP_ACT] = 1 + 1, 41 | [ASN1_OP_MAYBE_ACT] = 1 + 1, 42 | [ASN1_OP_RETURN] = 1, 43 | [ASN1_OP_END_SEQ] = 1, 44 | [ASN1_OP_END_SEQ_OF] = 1 + 1, 45 | [ASN1_OP_END_SET] = 1, 46 | [ASN1_OP_END_SET_OF] = 1 + 1, 47 | [ASN1_OP_END_SEQ_ACT] = 1 + 1, 48 | [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, 49 | [ASN1_OP_END_SET_ACT] = 1 + 1, 50 | [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, 51 | }; 52 | 53 | /* 54 | * Find the length of an indefinite length object 55 | * @data: The data buffer 56 | * @datalen: The end of the innermost containing element in the buffer 57 | * @_dp: The data parse cursor (updated before returning) 58 | * @_len: Where to return the size of the element. 59 | * @_errmsg: Where to return a pointer to an error message on error 60 | */ 61 | static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, 62 | size_t *_dp, size_t *_len, 63 | const char **_errmsg) 64 | { 65 | unsigned char tag, tmp; 66 | size_t dp = *_dp, len, n; 67 | int indef_level = 1; 68 | 69 | next_tag: 70 | if (unlikely(datalen - dp < 2)) { 71 | if (datalen == dp) 72 | goto missing_eoc; 73 | goto data_overrun_error; 74 | } 75 | 76 | /* Extract a tag from the data */ 77 | tag = data[dp++]; 78 | if (tag == ASN1_EOC) { 79 | /* It appears to be an EOC. */ 80 | if (data[dp++] != 0) 81 | goto invalid_eoc; 82 | if (--indef_level <= 0) { 83 | *_len = dp - *_dp; 84 | *_dp = dp; 85 | return 0; 86 | } 87 | goto next_tag; 88 | } 89 | 90 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) { 91 | do { 92 | if (unlikely(datalen - dp < 2)) 93 | goto data_overrun_error; 94 | tmp = data[dp++]; 95 | } while (tmp & 0x80); 96 | } 97 | 98 | /* Extract the length */ 99 | len = data[dp++]; 100 | if (len <= 0x7f) 101 | goto check_length; 102 | 103 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { 104 | /* Indefinite length */ 105 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) 106 | goto indefinite_len_primitive; 107 | indef_level++; 108 | goto next_tag; 109 | } 110 | 111 | n = len - 0x80; 112 | if (unlikely(n > sizeof(len) - 1)) 113 | goto length_too_long; 114 | if (unlikely(n > datalen - dp)) 115 | goto data_overrun_error; 116 | len = 0; 117 | for (; n > 0; n--) { 118 | len <<= 8; 119 | len |= data[dp++]; 120 | } 121 | check_length: 122 | if (len > datalen - dp) 123 | goto data_overrun_error; 124 | dp += len; 125 | goto next_tag; 126 | 127 | length_too_long: 128 | *_errmsg = "Unsupported length (in asn1_find_indefinite_length)"; 129 | goto error; 130 | indefinite_len_primitive: 131 | *_errmsg = "Indefinite len primitive not permitted (in asn1_find_indefinite_length)"; 132 | goto error; 133 | invalid_eoc: 134 | *_errmsg = "Invalid length EOC (in asn1_find_indefinite_length)"; 135 | goto error; 136 | data_overrun_error: 137 | *_errmsg = "Data overrun error (in asn1_find_indefinite_length)"; 138 | goto error; 139 | missing_eoc: 140 | *_errmsg = "Missing EOC in indefinite len cons"; 141 | error: 142 | *_dp = dp; 143 | return -1; 144 | } 145 | 146 | /** 147 | * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern 148 | * @decoder: The decoder definition (produced by asn1_compiler) 149 | * @context: The caller's context (to be passed to the action functions) 150 | * @data: The encoded data 151 | * @datalen: The size of the encoded data 152 | * 153 | * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern 154 | * produced by asn1_compiler. Action functions are called on marked tags to 155 | * allow the caller to retrieve significant data. 156 | * 157 | * LIMITATIONS: 158 | * 159 | * To keep down the amount of stack used by this function, the following limits 160 | * have been imposed: 161 | * 162 | * (1) This won't handle datalen > 65535 without increasing the size of the 163 | * cons stack elements and length_too_long checking. 164 | * 165 | * (2) The stack of constructed types is 10 deep. If the depth of non-leaf 166 | * constructed types exceeds this, the decode will fail. 167 | * 168 | * (3) The SET type (not the SET OF type) isn't really supported as tracking 169 | * what members of the set have been seen is a pain. 170 | */ 171 | int asn1_ber_decoder(const struct asn1_decoder *decoder, 172 | void *context, 173 | const unsigned char *data, 174 | size_t datalen) 175 | { 176 | const unsigned char *machine = decoder->machine; 177 | const asn1_action_t *actions = decoder->actions; 178 | size_t machlen = decoder->machlen; 179 | enum asn1_opcode op; 180 | unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; 181 | const char *errmsg; 182 | size_t pc = 0, dp = 0, tdp = 0, len = 0; 183 | int ret; 184 | 185 | unsigned char flags = 0; 186 | #define FLAG_INDEFINITE_LENGTH 0x01 187 | #define FLAG_MATCHED 0x02 188 | #define FLAG_LAST_MATCHED 0x04 /* Last tag matched */ 189 | #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag 190 | * - ie. whether or not we are going to parse 191 | * a compound type. 192 | */ 193 | 194 | #define NR_CONS_STACK 10 195 | unsigned short cons_dp_stack[NR_CONS_STACK]; 196 | unsigned short cons_datalen_stack[NR_CONS_STACK]; 197 | unsigned char cons_hdrlen_stack[NR_CONS_STACK]; 198 | #define NR_JUMP_STACK 10 199 | unsigned char jump_stack[NR_JUMP_STACK]; 200 | 201 | if (datalen > 65535) 202 | return -EMSGSIZE; 203 | 204 | next_op: 205 | pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", 206 | pc, machlen, dp, datalen, csp, jsp); 207 | if (unlikely(pc >= machlen)) 208 | goto machine_overrun_error; 209 | op = machine[pc]; 210 | if (unlikely(pc + asn1_op_lengths[op] > machlen)) 211 | goto machine_overrun_error; 212 | 213 | /* If this command is meant to match a tag, then do that before 214 | * evaluating the command. 215 | */ 216 | if (op <= ASN1_OP__MATCHES_TAG) { 217 | unsigned char tmp; 218 | 219 | /* Skip conditional matches if possible */ 220 | if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || 221 | (op & ASN1_OP_MATCH__SKIP && dp == datalen)) { 222 | flags &= ~FLAG_LAST_MATCHED; 223 | pc += asn1_op_lengths[op]; 224 | goto next_op; 225 | } 226 | 227 | flags = 0; 228 | hdr = 2; 229 | 230 | /* Extract a tag from the data */ 231 | if (unlikely(datalen - dp < 2)) { 232 | pr_debug("dp >= datalen - 1 - dp %lu datalen %lu\n", dp, datalen); 233 | goto data_overrun_error; 234 | } 235 | tag = data[dp++]; 236 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) 237 | goto long_tag_not_supported; 238 | 239 | if (op & ASN1_OP_MATCH__ANY) { 240 | pr_debug("- any %02x\n", tag); 241 | } else { 242 | /* Extract the tag from the machine 243 | * - Either CONS or PRIM are permitted in the data if 244 | * CONS is not set in the op stream, otherwise CONS 245 | * is mandatory. 246 | */ 247 | optag = machine[pc + 1]; 248 | flags |= optag & FLAG_CONS; 249 | 250 | /* Determine whether the tag matched */ 251 | tmp = optag ^ tag; 252 | tmp &= ~(optag & ASN1_CONS_BIT); 253 | pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); 254 | if (tmp != 0) { 255 | /* All odd-numbered tags are MATCH_OR_SKIP. */ 256 | if (op & ASN1_OP_MATCH__SKIP) { 257 | pc += asn1_op_lengths[op]; 258 | dp--; 259 | goto next_op; 260 | } 261 | goto tag_mismatch; 262 | } 263 | } 264 | flags |= FLAG_MATCHED; 265 | 266 | len = data[dp++]; 267 | if (len > 0x7f) { 268 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { 269 | /* Indefinite length */ 270 | if (unlikely(!(tag & ASN1_CONS_BIT))) 271 | goto indefinite_len_primitive; 272 | flags |= FLAG_INDEFINITE_LENGTH; 273 | if (unlikely(2 > datalen - dp)) 274 | goto data_overrun_error; 275 | } else { 276 | int n = len - 0x80; 277 | if (unlikely(n > 2)) 278 | goto length_too_long; 279 | if (unlikely(n > datalen - dp)) 280 | goto data_overrun_error; 281 | hdr += n; 282 | for (len = 0; n > 0; n--) { 283 | len <<= 8; 284 | len |= data[dp++]; 285 | } 286 | if (unlikely(len > datalen - dp)) 287 | goto data_overrun_error; 288 | } 289 | } else { 290 | if (unlikely(len > datalen - dp)) 291 | goto data_overrun_error; 292 | } 293 | 294 | if (flags & FLAG_CONS) { 295 | /* For expected compound forms, we stack the positions 296 | * of the start and end of the data. 297 | */ 298 | if (unlikely(csp >= NR_CONS_STACK)) 299 | goto cons_stack_overflow; 300 | cons_dp_stack[csp] = dp; 301 | cons_hdrlen_stack[csp] = hdr; 302 | if (!(flags & FLAG_INDEFINITE_LENGTH)) { 303 | cons_datalen_stack[csp] = datalen; 304 | datalen = dp + len; 305 | } else { 306 | cons_datalen_stack[csp] = 0; 307 | } 308 | csp++; 309 | } 310 | 311 | pr_debug("- TAG: %02x %zu%s\n", 312 | tag, len, flags & FLAG_CONS ? " CONS" : ""); 313 | tdp = dp; 314 | } 315 | 316 | /* Decide how to handle the operation */ 317 | switch (op) { 318 | case ASN1_OP_MATCH: 319 | case ASN1_OP_MATCH_OR_SKIP: 320 | case ASN1_OP_MATCH_ACT: 321 | case ASN1_OP_MATCH_ACT_OR_SKIP: 322 | case ASN1_OP_MATCH_ANY: 323 | case ASN1_OP_MATCH_ANY_OR_SKIP: 324 | case ASN1_OP_MATCH_ANY_ACT: 325 | case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: 326 | case ASN1_OP_COND_MATCH_OR_SKIP: 327 | case ASN1_OP_COND_MATCH_ACT_OR_SKIP: 328 | case ASN1_OP_COND_MATCH_ANY: 329 | case ASN1_OP_COND_MATCH_ANY_OR_SKIP: 330 | case ASN1_OP_COND_MATCH_ANY_ACT: 331 | case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: 332 | 333 | if (!(flags & FLAG_CONS)) { 334 | if (flags & FLAG_INDEFINITE_LENGTH) { 335 | size_t tmp = dp; 336 | 337 | ret = asn1_find_indefinite_length( 338 | data, datalen, &tmp, &len, &errmsg); 339 | if (ret < 0) 340 | goto error; 341 | } 342 | pr_debug("- LEAF: %zu\n", len); 343 | } 344 | 345 | if (op & ASN1_OP_MATCH__ACT) { 346 | unsigned char act; 347 | 348 | if (op & ASN1_OP_MATCH__ANY) 349 | act = machine[pc + 1]; 350 | else 351 | act = machine[pc + 2]; 352 | ret = actions[act](context, hdr, tag, data + dp, len); 353 | if (ret < 0) 354 | return ret; 355 | } 356 | 357 | if (!(flags & FLAG_CONS)) 358 | dp += len; 359 | pc += asn1_op_lengths[op]; 360 | goto next_op; 361 | 362 | case ASN1_OP_MATCH_JUMP: 363 | case ASN1_OP_MATCH_JUMP_OR_SKIP: 364 | case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: 365 | pr_debug("- MATCH_JUMP\n"); 366 | if (unlikely(jsp == NR_JUMP_STACK)) 367 | goto jump_stack_overflow; 368 | jump_stack[jsp++] = pc + asn1_op_lengths[op]; 369 | pc = machine[pc + 2]; 370 | goto next_op; 371 | 372 | case ASN1_OP_COND_FAIL: 373 | if (unlikely(!(flags & FLAG_MATCHED))) 374 | goto tag_mismatch; 375 | pc += asn1_op_lengths[op]; 376 | goto next_op; 377 | 378 | case ASN1_OP_COMPLETE: 379 | if (unlikely(jsp != 0 || csp != 0)) { 380 | pr_err("ERROR: ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", 381 | jsp, csp); 382 | return -EBADMSG; 383 | } 384 | return 0; 385 | 386 | case ASN1_OP_END_SET: 387 | case ASN1_OP_END_SET_ACT: 388 | if (unlikely(!(flags & FLAG_MATCHED))) 389 | goto tag_mismatch; 390 | case ASN1_OP_END_SEQ: 391 | case ASN1_OP_END_SET_OF: 392 | case ASN1_OP_END_SEQ_OF: 393 | case ASN1_OP_END_SEQ_ACT: 394 | case ASN1_OP_END_SET_OF_ACT: 395 | case ASN1_OP_END_SEQ_OF_ACT: 396 | if (unlikely(csp <= 0)) 397 | goto cons_stack_underflow; 398 | csp--; 399 | tdp = cons_dp_stack[csp]; 400 | hdr = cons_hdrlen_stack[csp]; 401 | len = datalen; 402 | datalen = cons_datalen_stack[csp]; 403 | pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", 404 | tdp, dp, len, datalen); 405 | if (datalen == 0) { 406 | /* Indefinite length - check for the EOC. */ 407 | datalen = len; 408 | if (unlikely(datalen - dp < 2)) 409 | goto data_overrun_error; 410 | if (data[dp++] != 0) { 411 | if (op & ASN1_OP_END__OF) { 412 | dp--; 413 | csp++; 414 | pc = machine[pc + 1]; 415 | pr_debug("- continue\n"); 416 | goto next_op; 417 | } 418 | goto missing_eoc; 419 | } 420 | if (data[dp++] != 0) 421 | goto invalid_eoc; 422 | len = dp - tdp - 2; 423 | } else { 424 | if (dp < len && (op & ASN1_OP_END__OF)) { 425 | datalen = len; 426 | csp++; 427 | pc = machine[pc + 1]; 428 | pr_debug("- continue\n"); 429 | goto next_op; 430 | } 431 | if (dp != len) 432 | goto cons_length_error; 433 | len -= tdp; 434 | pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); 435 | } 436 | 437 | if (op & ASN1_OP_END__ACT) { 438 | unsigned char act; 439 | if (op & ASN1_OP_END__OF) 440 | act = machine[pc + 2]; 441 | else 442 | act = machine[pc + 1]; 443 | ret = actions[act](context, hdr, 0, data + tdp, len); 444 | if (ret < 0) 445 | return ret; 446 | } 447 | pc += asn1_op_lengths[op]; 448 | goto next_op; 449 | 450 | case ASN1_OP_MAYBE_ACT: 451 | if (!(flags & FLAG_LAST_MATCHED)) { 452 | pc += asn1_op_lengths[op]; 453 | goto next_op; 454 | } 455 | case ASN1_OP_ACT: 456 | ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); 457 | if (ret < 0) 458 | return ret; 459 | pc += asn1_op_lengths[op]; 460 | goto next_op; 461 | 462 | case ASN1_OP_RETURN: 463 | if (unlikely(jsp <= 0)) 464 | goto jump_stack_underflow; 465 | pc = jump_stack[--jsp]; 466 | flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; 467 | goto next_op; 468 | 469 | default: 470 | break; 471 | } 472 | 473 | /* Shouldn't reach here */ 474 | pr_err("ERROR: ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n", 475 | op, pc); 476 | return -EBADMSG; 477 | 478 | data_overrun_error: 479 | errmsg = "Data overrun error"; 480 | goto error; 481 | machine_overrun_error: 482 | errmsg = "Machine overrun error"; 483 | goto error; 484 | jump_stack_underflow: 485 | errmsg = "Jump stack underflow"; 486 | goto error; 487 | jump_stack_overflow: 488 | errmsg = "Jump stack overflow"; 489 | goto error; 490 | cons_stack_underflow: 491 | errmsg = "Cons stack underflow"; 492 | goto error; 493 | cons_stack_overflow: 494 | errmsg = "Cons stack overflow"; 495 | goto error; 496 | cons_length_error: 497 | errmsg = "Cons length error"; 498 | goto error; 499 | missing_eoc: 500 | errmsg = "Missing EOC in indefinite len cons"; 501 | goto error; 502 | invalid_eoc: 503 | errmsg = "Invalid length EOC"; 504 | goto error; 505 | length_too_long: 506 | errmsg = "Unsupported length"; 507 | goto error; 508 | indefinite_len_primitive: 509 | errmsg = "Indefinite len primitive not permitted"; 510 | goto error; 511 | tag_mismatch: 512 | errmsg = "Unexpected tag"; 513 | goto error; 514 | long_tag_not_supported: 515 | errmsg = "Long tag not supported"; 516 | error: 517 | pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", 518 | errmsg, pc, dp, optag, tag, len); 519 | return -EBADMSG; 520 | } 521 | -------------------------------------------------------------------------------- /asn/misc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int read_file(char * filename, char *buffer, long length) 7 | { 8 | FILE *fp; 9 | long fsize, total = 0, num_read; 10 | 11 | fp = fopen(filename, "rb"); 12 | if (!fp) 13 | return -1; 14 | 15 | //Get the size 16 | fseek(fp, 0, SEEK_END); 17 | fsize = ftell(fp); 18 | fseek(fp, 0, SEEK_SET); 19 | 20 | if(fsize > length) 21 | fsize = length; 22 | 23 | while (total < fsize) 24 | { 25 | num_read = fread(buffer + total, 1, fsize, fp); 26 | total += num_read; 27 | } 28 | 29 | fclose(fp); 30 | 31 | return fsize; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /asn/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef __MISC_H__ 2 | #define __MISC_H__ 3 | 4 | #define fips_enabled 0 5 | 6 | #define unlikely(x) x 7 | #ifdef DEBUG 8 | #define pr_devel printf 9 | #define pr_debug printf 10 | #define pr_warn printf 11 | #define pr_err printf 12 | #define printk printf 13 | #else 14 | #define pr_devel(...) 15 | #define pr_debug(...) 16 | #define pr_warn(...) 17 | #define pr_err(...) 18 | #define printk(...) 19 | #endif 20 | 21 | #define u8 unsigned char 22 | #define u16 unsigned short 23 | #define time64_t int64_t 24 | #define bool int 25 | 26 | //Taken from include/linux/err.h: 27 | 28 | #define MAX_ERRNO 4095 29 | #define IS_ERR_VALUE(x) ((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) 30 | 31 | static inline void * ERR_PTR(long error) 32 | { 33 | return (void *) error; 34 | } 35 | 36 | static inline long PTR_ERR(const void *ptr) 37 | { 38 | return (long) ptr; 39 | } 40 | 41 | static inline bool IS_ERR(const void *ptr) 42 | { 43 | return IS_ERR_VALUE((unsigned long)ptr); 44 | } 45 | 46 | int read_file(char * filename, char *buffer, long length); 47 | 48 | #endif //__MISC_H__ 49 | -------------------------------------------------------------------------------- /asn/oid_registry.c: -------------------------------------------------------------------------------- 1 | /* ASN.1 Object identifier (OID) registry 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "oid_registry.h" 18 | #include "oid_registry_data.c" 19 | 20 | /** 21 | * look_up_OID - Find an OID registration for the specified data 22 | * @data: Binary representation of the OID 23 | * @datasize: Size of the binary representation 24 | */ 25 | enum OID look_up_OID(const void *data, size_t datasize) 26 | { 27 | const unsigned char *octets = data; 28 | enum OID oid; 29 | unsigned char xhash; 30 | unsigned i, j, k, hash; 31 | size_t len; 32 | 33 | /* Hash the OID data */ 34 | hash = datasize - 1; 35 | 36 | for (i = 0; i < datasize; i++) 37 | hash += octets[i] * 33; 38 | hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; 39 | hash &= 0xff; 40 | 41 | /* Binary search the OID registry. OIDs are stored in ascending order 42 | * of hash value then ascending order of size and then in ascending 43 | * order of reverse value. 44 | */ 45 | i = 0; 46 | k = OID__NR; 47 | while (i < k) { 48 | j = (i + k) / 2; 49 | 50 | xhash = oid_search_table[j].hash; 51 | if (xhash > hash) { 52 | k = j; 53 | continue; 54 | } 55 | if (xhash < hash) { 56 | i = j + 1; 57 | continue; 58 | } 59 | 60 | oid = oid_search_table[j].oid; 61 | len = oid_index[oid + 1] - oid_index[oid]; 62 | if (len > datasize) { 63 | k = j; 64 | continue; 65 | } 66 | if (len < datasize) { 67 | i = j + 1; 68 | continue; 69 | } 70 | 71 | /* Variation is most likely to be at the tail end of the 72 | * OID, so do the comparison in reverse. 73 | */ 74 | while (len > 0) { 75 | unsigned char a = oid_data[oid_index[oid] + --len]; 76 | unsigned char b = octets[len]; 77 | if (a > b) { 78 | k = j; 79 | goto next; 80 | } 81 | if (a < b) { 82 | i = j + 1; 83 | goto next; 84 | } 85 | } 86 | return oid; 87 | next: 88 | ; 89 | } 90 | 91 | return OID__NR; 92 | } 93 | 94 | /* 95 | * sprint_OID - Print an Object Identifier into a buffer 96 | * @data: The encoded OID to print 97 | * @datasize: The size of the encoded OID 98 | * @buffer: The buffer to render into 99 | * @bufsize: The size of the buffer 100 | * 101 | * The OID is rendered into the buffer in "a.b.c.d" format and the number of 102 | * bytes is returned. -EBADMSG is returned if the data could not be intepreted 103 | * and -ENOBUFS if the buffer was too small. 104 | */ 105 | int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) 106 | { 107 | const unsigned char *v = data, *end = v + datasize; 108 | unsigned long num; 109 | unsigned char n; 110 | size_t ret; 111 | int count; 112 | 113 | if (v >= end) 114 | return -EBADMSG; 115 | 116 | n = *v++; 117 | ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); 118 | buffer += count; 119 | bufsize -= count; 120 | if (bufsize == 0) 121 | return -ENOBUFS; 122 | 123 | while (v < end) { 124 | num = 0; 125 | n = *v++; 126 | if (!(n & 0x80)) { 127 | num = n; 128 | } else { 129 | num = n & 0x7f; 130 | do { 131 | if (v >= end) 132 | return -EBADMSG; 133 | n = *v++; 134 | num <<= 7; 135 | num |= n & 0x7f; 136 | } while (n & 0x80); 137 | } 138 | ret += count = snprintf(buffer, bufsize, ".%lu", num); 139 | buffer += count; 140 | if (bufsize <= count) 141 | return -ENOBUFS; 142 | bufsize -= count; 143 | } 144 | 145 | return ret; 146 | } 147 | 148 | /** 149 | * sprint_OID - Print an Object Identifier into a buffer 150 | * @oid: The OID to print 151 | * @buffer: The buffer to render into 152 | * @bufsize: The size of the buffer 153 | * 154 | * The OID is rendered into the buffer in "a.b.c.d" format and the number of 155 | * bytes is returned. 156 | */ 157 | int sprint_OID(enum OID oid, char *buffer, size_t bufsize) 158 | { 159 | int ret; 160 | 161 | if(oid >= OID__NR) { printf("BUG_ON: oid >= OID__NR\n"); exit(1); } 162 | 163 | ret = sprint_oid(oid_data + oid_index[oid], 164 | oid_index[oid + 1] - oid_index[oid], 165 | buffer, bufsize); 166 | if(ret == -EBADMSG) { printf("BUG_ON: ret == -EBADMSG\n"); exit(1); } 167 | return ret; 168 | } 169 | -------------------------------------------------------------------------------- /asn/oid_registry.h: -------------------------------------------------------------------------------- 1 | /* ASN.1 Object identifier (OID) registry 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef _LINUX_OID_REGISTRY_H 13 | #define _LINUX_OID_REGISTRY_H 14 | 15 | #include 16 | 17 | /* 18 | * OIDs are turned into these values if possible, or OID__NR if not held here. 19 | * 20 | * NOTE! Do not mess with the format of each line as this is read by 21 | * build_OID_registry.pl to generate the data for look_up_OID(). 22 | */ 23 | enum OID { 24 | OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ 25 | OID_id_dsa, /* 1.2.840.10040.4.1 */ 26 | OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ 27 | OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ 28 | 29 | /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ 30 | OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ 31 | OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ 32 | OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ 33 | OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ 34 | OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ 35 | OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ 36 | OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ 37 | OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ 38 | OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ 39 | /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ 40 | OID_data, /* 1.2.840.113549.1.7.1 */ 41 | OID_signed_data, /* 1.2.840.113549.1.7.2 */ 42 | /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ 43 | OID_email_address, /* 1.2.840.113549.1.9.1 */ 44 | OID_content_type, /* 1.2.840.113549.1.9.3 */ 45 | OID_messageDigest, /* 1.2.840.113549.1.9.4 */ 46 | OID_signingTime, /* 1.2.840.113549.1.9.5 */ 47 | OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ 48 | OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ 49 | 50 | /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ 51 | OID_md2, /* 1.2.840.113549.2.2 */ 52 | OID_md4, /* 1.2.840.113549.2.4 */ 53 | OID_md5, /* 1.2.840.113549.2.5 */ 54 | 55 | /* Microsoft Authenticode & Software Publishing */ 56 | OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */ 57 | OID_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */ 58 | OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */ 59 | OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ 60 | 61 | OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ 62 | OID_sha1, /* 1.3.14.3.2.26 */ 63 | OID_sha256, /* 2.16.840.1.101.3.4.2.1 */ 64 | 65 | /* Distinguished Name attribute IDs [RFC 2256] */ 66 | OID_commonName, /* 2.5.4.3 */ 67 | OID_surname, /* 2.5.4.4 */ 68 | OID_countryName, /* 2.5.4.6 */ 69 | OID_locality, /* 2.5.4.7 */ 70 | OID_stateOrProvinceName, /* 2.5.4.8 */ 71 | OID_organizationName, /* 2.5.4.10 */ 72 | OID_organizationUnitName, /* 2.5.4.11 */ 73 | OID_title, /* 2.5.4.12 */ 74 | OID_description, /* 2.5.4.13 */ 75 | OID_name, /* 2.5.4.41 */ 76 | OID_givenName, /* 2.5.4.42 */ 77 | OID_initials, /* 2.5.4.43 */ 78 | OID_generationalQualifier, /* 2.5.4.44 */ 79 | 80 | /* Certificate extension IDs */ 81 | OID_subjectKeyIdentifier, /* 2.5.29.14 */ 82 | OID_keyUsage, /* 2.5.29.15 */ 83 | OID_subjectAltName, /* 2.5.29.17 */ 84 | OID_issuerAltName, /* 2.5.29.18 */ 85 | OID_basicConstraints, /* 2.5.29.19 */ 86 | OID_crlDistributionPoints, /* 2.5.29.31 */ 87 | OID_certPolicies, /* 2.5.29.32 */ 88 | OID_authorityKeyIdentifier, /* 2.5.29.35 */ 89 | OID_extKeyUsage, /* 2.5.29.37 */ 90 | 91 | OID__NR 92 | }; 93 | 94 | extern enum OID look_up_OID(const void *data, size_t datasize); 95 | extern int sprint_oid(const void *, size_t, char *, size_t); 96 | extern int sprint_OID(enum OID, char *, size_t); 97 | 98 | #endif /* _LINUX_OID_REGISTRY_H */ 99 | -------------------------------------------------------------------------------- /asn/oid_registry_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by ./lib/build_OID_registry. Do not edit 3 | */ 4 | 5 | static const unsigned short oid_index[OID__NR + 1] = { 6 | [OID_id_dsa_with_sha1] = 0, 7 | [OID_id_dsa] = 7, 8 | [OID_id_ecdsa_with_sha1] = 14, 9 | [OID_id_ecPublicKey] = 21, 10 | [OID_rsaEncryption] = 28, 11 | [OID_md2WithRSAEncryption] = 37, 12 | [OID_md3WithRSAEncryption] = 46, 13 | [OID_md4WithRSAEncryption] = 55, 14 | [OID_sha1WithRSAEncryption] = 64, 15 | [OID_sha256WithRSAEncryption] = 73, 16 | [OID_sha384WithRSAEncryption] = 82, 17 | [OID_sha512WithRSAEncryption] = 91, 18 | [OID_sha224WithRSAEncryption] = 100, 19 | [OID_data] = 109, 20 | [OID_signed_data] = 118, 21 | [OID_email_address] = 127, 22 | [OID_content_type] = 136, 23 | [OID_messageDigest] = 145, 24 | [OID_signingTime] = 154, 25 | [OID_smimeCapabilites] = 163, 26 | [OID_smimeAuthenticatedAttrs] = 172, 27 | [OID_md2] = 183, 28 | [OID_md4] = 191, 29 | [OID_md5] = 199, 30 | [OID_msIndirectData] = 207, 31 | [OID_msPeImageDataObjId] = 217, 32 | [OID_msIndividualSPKeyPurpose] = 227, 33 | [OID_msOutlookExpress] = 237, 34 | [OID_certAuthInfoAccess] = 246, 35 | [OID_sha1] = 254, 36 | [OID_sha256] = 259, 37 | [OID_commonName] = 268, 38 | [OID_surname] = 271, 39 | [OID_countryName] = 274, 40 | [OID_locality] = 277, 41 | [OID_stateOrProvinceName] = 280, 42 | [OID_organizationName] = 283, 43 | [OID_organizationUnitName] = 286, 44 | [OID_title] = 289, 45 | [OID_description] = 292, 46 | [OID_name] = 295, 47 | [OID_givenName] = 298, 48 | [OID_initials] = 301, 49 | [OID_generationalQualifier] = 304, 50 | [OID_subjectKeyIdentifier] = 307, 51 | [OID_keyUsage] = 310, 52 | [OID_subjectAltName] = 313, 53 | [OID_issuerAltName] = 316, 54 | [OID_basicConstraints] = 319, 55 | [OID_crlDistributionPoints] = 322, 56 | [OID_certPolicies] = 325, 57 | [OID_authorityKeyIdentifier] = 328, 58 | [OID_extKeyUsage] = 331, 59 | [OID__NR] = 334 60 | }; 61 | 62 | static const unsigned char oid_data[334] = { 63 | 42, 134, 72, 206, 46, 4, 3, // id_dsa_with_sha1 64 | 42, 134, 72, 206, 56, 4, 1, // id_dsa 65 | 42, 134, 72, 206, 61, 4, 1, // id_ecdsa_with_sha1 66 | 42, 134, 72, 206, 61, 2, 1, // id_ecPublicKey 67 | 42, 134, 72, 134, 247, 13, 1, 1, 1, // rsaEncryption 68 | 42, 134, 72, 134, 247, 13, 1, 1, 2, // md2WithRSAEncryption 69 | 42, 134, 72, 134, 247, 13, 1, 1, 3, // md3WithRSAEncryption 70 | 42, 134, 72, 134, 247, 13, 1, 1, 4, // md4WithRSAEncryption 71 | 42, 134, 72, 134, 247, 13, 1, 1, 5, // sha1WithRSAEncryption 72 | 42, 134, 72, 134, 247, 13, 1, 1, 11, // sha256WithRSAEncryption 73 | 42, 134, 72, 134, 247, 13, 1, 1, 12, // sha384WithRSAEncryption 74 | 42, 134, 72, 134, 247, 13, 1, 1, 13, // sha512WithRSAEncryption 75 | 42, 134, 72, 134, 247, 13, 1, 1, 14, // sha224WithRSAEncryption 76 | 42, 134, 72, 134, 247, 13, 1, 7, 1, // data 77 | 42, 134, 72, 134, 247, 13, 1, 7, 2, // signed_data 78 | 42, 134, 72, 134, 247, 13, 1, 9, 1, // email_address 79 | 42, 134, 72, 134, 247, 13, 1, 9, 3, // content_type 80 | 42, 134, 72, 134, 247, 13, 1, 9, 4, // messageDigest 81 | 42, 134, 72, 134, 247, 13, 1, 9, 5, // signingTime 82 | 42, 134, 72, 134, 247, 13, 1, 9, 15, // smimeCapabilites 83 | 42, 134, 72, 134, 247, 13, 1, 9, 16, 2, 11, // smimeAuthenticatedAttrs 84 | 42, 134, 72, 134, 247, 13, 2, 2, // md2 85 | 42, 134, 72, 134, 247, 13, 2, 4, // md4 86 | 42, 134, 72, 134, 247, 13, 2, 5, // md5 87 | 43, 6, 1, 4, 1, 130, 55, 2, 1, 4, // msIndirectData 88 | 43, 6, 1, 4, 1, 130, 55, 2, 1, 15, // msPeImageDataObjId 89 | 43, 6, 1, 4, 1, 130, 55, 2, 1, 21, // msIndividualSPKeyPurpose 90 | 43, 6, 1, 4, 1, 130, 55, 16, 4, // msOutlookExpress 91 | 43, 6, 1, 5, 5, 7, 1, 1, // certAuthInfoAccess 92 | 43, 14, 3, 2, 26, // sha1 93 | 96, 134, 72, 1, 101, 3, 4, 2, 1, // sha256 94 | 85, 4, 3, // commonName 95 | 85, 4, 4, // surname 96 | 85, 4, 6, // countryName 97 | 85, 4, 7, // locality 98 | 85, 4, 8, // stateOrProvinceName 99 | 85, 4, 10, // organizationName 100 | 85, 4, 11, // organizationUnitName 101 | 85, 4, 12, // title 102 | 85, 4, 13, // description 103 | 85, 4, 41, // name 104 | 85, 4, 42, // givenName 105 | 85, 4, 43, // initials 106 | 85, 4, 44, // generationalQualifier 107 | 85, 29, 14, // subjectKeyIdentifier 108 | 85, 29, 15, // keyUsage 109 | 85, 29, 17, // subjectAltName 110 | 85, 29, 18, // issuerAltName 111 | 85, 29, 19, // basicConstraints 112 | 85, 29, 31, // crlDistributionPoints 113 | 85, 29, 32, // certPolicies 114 | 85, 29, 35, // authorityKeyIdentifier 115 | 85, 29, 37, // extKeyUsage 116 | }; 117 | 118 | static const struct { 119 | unsigned char hash; 120 | enum OID oid : 8; 121 | } oid_search_table[OID__NR] = { 122 | [ 0] = { 10, OID_title }, // 55040c 123 | [ 1] = { 23, OID_issuerAltName }, // 551d12 124 | [ 2] = { 23, OID_initials }, // 55042b 125 | [ 3] = { 29, OID_md2WithRSAEncryption }, // 2a864886f70d010102 126 | [ 4] = { 30, OID_md2 }, // 2a864886f70d0202 127 | [ 5] = { 32, OID_id_dsa_with_sha1 }, // 2a8648ce2e0403 128 | [ 6] = { 35, OID_content_type }, // 2a864886f70d010903 129 | [ 7] = { 35, OID_sha256WithRSAEncryption }, // 2a864886f70d01010b 130 | [ 8] = { 36, OID_authorityKeyIdentifier }, // 551d23 131 | [ 9] = { 37, OID_description }, // 55040d 132 | [ 10] = { 43, OID_id_dsa }, // 2a8648ce380401 133 | [ 11] = { 51, OID_msIndividualSPKeyPurpose }, // 2b060104018237020115 134 | [ 12] = { 54, OID_basicConstraints }, // 551d13 135 | [ 13] = { 54, OID_generationalQualifier }, // 55042c 136 | [ 14] = { 60, OID_md3WithRSAEncryption }, // 2a864886f70d010103 137 | [ 15] = { 64, OID_signed_data }, // 2a864886f70d010702 138 | [ 16] = { 77, OID_countryName }, // 550406 139 | [ 17] = { 77, OID_id_ecdsa_with_sha1 }, // 2a8648ce3d0401 140 | [ 18] = { 83, OID_sha256 }, // 608648016503040201 141 | [ 19] = { 85, OID_smimeCapabilites }, // 2a864886f70d01090f 142 | [ 20] = { 87, OID_sha1 }, // 2b0e03021a 143 | [ 21] = { 97, OID_email_address }, // 2a864886f70d010901 144 | [ 22] = { 106, OID_extKeyUsage }, // 551d25 145 | [ 23] = { 106, OID_msPeImageDataObjId }, // 2b06010401823702010f 146 | [ 24] = { 110, OID_locality }, // 550407 147 | [ 25] = { 126, OID_rsaEncryption }, // 2a864886f70d010101 148 | [ 26] = { 132, OID_smimeAuthenticatedAttrs }, // 2a864886f70d010910020b 149 | [ 27] = { 142, OID_id_ecPublicKey }, // 2a8648ce3d0201 150 | [ 28] = { 142, OID_sha224WithRSAEncryption }, // 2a864886f70d01010e 151 | [ 29] = { 143, OID_stateOrProvinceName }, // 550408 152 | [ 30] = { 146, OID_subjectKeyIdentifier }, // 551d0e 153 | [ 31] = { 160, OID_data }, // 2a864886f70d010701 154 | [ 32] = { 161, OID_crlDistributionPoints }, // 551d1f 155 | [ 33] = { 173, OID_msOutlookExpress }, // 2b0601040182371004 156 | [ 34] = { 179, OID_keyUsage }, // 551d0f 157 | [ 35] = { 195, OID_md4WithRSAEncryption }, // 2a864886f70d010104 158 | [ 36] = { 198, OID_certPolicies }, // 551d20 159 | [ 37] = { 201, OID_organizationName }, // 55040a 160 | [ 38] = { 204, OID_messageDigest }, // 2a864886f70d010904 161 | [ 39] = { 204, OID_sha384WithRSAEncryption }, // 2a864886f70d01010c 162 | [ 40] = { 212, OID_name }, // 550429 163 | [ 41] = { 213, OID_commonName }, // 550403 164 | [ 42] = { 220, OID_md4 }, // 2a864886f70d0204 165 | [ 43] = { 226, OID_sha1WithRSAEncryption }, // 2a864886f70d010105 166 | [ 44] = { 227, OID_md5 }, // 2a864886f70d0205 167 | [ 45] = { 228, OID_certAuthInfoAccess }, // 2b06010505070101 168 | [ 46] = { 234, OID_organizationUnitName }, // 55040b 169 | [ 47] = { 237, OID_signingTime }, // 2a864886f70d010905 170 | [ 48] = { 237, OID_sha512WithRSAEncryption }, // 2a864886f70d01010d 171 | [ 49] = { 244, OID_surname }, // 550404 172 | [ 50] = { 245, OID_subjectAltName }, // 551d11 173 | [ 51] = { 245, OID_givenName }, // 55042a 174 | [ 52] = { 255, OID_msIndirectData }, // 2b060104018237020104 175 | }; 176 | -------------------------------------------------------------------------------- /asn/oob_read_1217.x509: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grimm-co/linuxklee/14e85ec2b8cbe89064f6e268aa3045f64ad1fce8/asn/oob_read_1217.x509 -------------------------------------------------------------------------------- /asn/oob_read_1396.x509: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grimm-co/linuxklee/14e85ec2b8cbe89064f6e268aa3045f64ad1fce8/asn/oob_read_1396.x509 -------------------------------------------------------------------------------- /asn/oob_read_928.x509: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grimm-co/linuxklee/14e85ec2b8cbe89064f6e268aa3045f64ad1fce8/asn/oob_read_928.x509 -------------------------------------------------------------------------------- /asn/pkcs7-asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for pkcs7 5 | */ 6 | #include "asn1_ber_bytecode.h" 7 | #include "pkcs7-asn1.h" 8 | 9 | enum pkcs7_actions { 10 | ACT_pkcs7_extract_cert = 0, 11 | ACT_pkcs7_note_OID = 1, 12 | ACT_pkcs7_note_certificate_list = 2, 13 | ACT_pkcs7_note_data = 3, 14 | ACT_pkcs7_note_signed_info = 4, 15 | ACT_pkcs7_sig_note_authenticated_attr = 5, 16 | ACT_pkcs7_sig_note_digest_algo = 6, 17 | ACT_pkcs7_sig_note_issuer = 7, 18 | ACT_pkcs7_sig_note_pkey_algo = 8, 19 | ACT_pkcs7_sig_note_serial = 9, 20 | ACT_pkcs7_sig_note_set_of_authattrs = 10, 21 | ACT_pkcs7_sig_note_signature = 11, 22 | NR__pkcs7_actions = 12 23 | }; 24 | 25 | static const asn1_action_t pkcs7_action_table[NR__pkcs7_actions] = { 26 | [ 0] = pkcs7_extract_cert, 27 | [ 1] = pkcs7_note_OID, 28 | [ 2] = pkcs7_note_certificate_list, 29 | [ 3] = pkcs7_note_data, 30 | [ 4] = pkcs7_note_signed_info, 31 | [ 5] = pkcs7_sig_note_authenticated_attr, 32 | [ 6] = pkcs7_sig_note_digest_algo, 33 | [ 7] = pkcs7_sig_note_issuer, 34 | [ 8] = pkcs7_sig_note_pkey_algo, 35 | [ 9] = pkcs7_sig_note_serial, 36 | [ 10] = pkcs7_sig_note_set_of_authattrs, 37 | [ 11] = pkcs7_sig_note_signature, 38 | }; 39 | 40 | static const unsigned char pkcs7_machine[] = { 41 | // PKCS7ContentInfo 42 | [ 0] = ASN1_OP_MATCH, 43 | [ 1] = _tag(UNIV, CONS, SEQ), 44 | // ContentType 45 | [ 2] = ASN1_OP_MATCH_ACT, 46 | [ 3] = _tag(UNIV, PRIM, OID), 47 | [ 4] = _action(ACT_pkcs7_note_OID), 48 | [ 5] = ASN1_OP_MATCH_JUMP_OR_SKIP, // content 49 | [ 6] = _tagn(CONT, CONS, 0), 50 | [ 7] = _jump_target(10), 51 | [ 8] = ASN1_OP_END_SEQ, 52 | [ 9] = ASN1_OP_COMPLETE, 53 | 54 | // SignedData 55 | [ 10] = ASN1_OP_MATCH, 56 | [ 11] = _tag(UNIV, CONS, SEQ), 57 | [ 12] = ASN1_OP_MATCH, // version 58 | [ 13] = _tag(UNIV, PRIM, INT), 59 | // DigestAlgorithmIdentifiers 60 | [ 14] = ASN1_OP_MATCH_JUMP_OR_SKIP, // daSet 61 | [ 15] = _tag(UNIV, CONS, SET), 62 | [ 16] = _jump_target(54), 63 | [ 17] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // daSequence 64 | [ 18] = _tag(UNIV, CONS, SEQ), 65 | [ 19] = _jump_target(60), 66 | [ 20] = ASN1_OP_COND_FAIL, 67 | // ContentInfo 68 | [ 21] = ASN1_OP_MATCH, 69 | [ 22] = _tag(UNIV, CONS, SEQ), 70 | // ContentType 71 | [ 23] = ASN1_OP_MATCH_ACT, 72 | [ 24] = _tag(UNIV, PRIM, OID), 73 | [ 25] = _action(ACT_pkcs7_note_OID), 74 | [ 26] = ASN1_OP_MATCH_JUMP_OR_SKIP, // content 75 | [ 27] = _tagn(CONT, CONS, 0), 76 | [ 28] = _jump_target(66), 77 | [ 29] = ASN1_OP_END_SEQ, 78 | // ExtendedCertificatesAndCertificates 79 | [ 30] = ASN1_OP_MATCH_JUMP_OR_SKIP, // certSet 80 | [ 31] = _tagn(CONT, CONS, 0), 81 | [ 32] = _jump_target(70), // --> ExtendedCertificatesAndCertificates 82 | // Certificates 83 | [ 33] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // certSequence 84 | [ 34] = _tagn(CONT, CONS, 2), 85 | [ 35] = _jump_target(78), // --> Certificates 86 | [ 36] = ASN1_OP_ACT, 87 | [ 37] = _action(ACT_pkcs7_note_certificate_list), 88 | // CertificateRevocationLists 89 | [ 38] = ASN1_OP_MATCH_JUMP_OR_SKIP, // crlSet 90 | [ 39] = _tagn(CONT, CONS, 1), 91 | [ 40] = _jump_target(83), // --> CertificateRevocationLists 92 | // CRLSequence 93 | [ 41] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // crlSequence 94 | [ 42] = _tagn(CONT, CONS, 3), 95 | [ 43] = _jump_target(89), // --> CRLSequence 96 | // SignerInfos 97 | [ 44] = ASN1_OP_MATCH_JUMP_OR_SKIP, // siSet 98 | [ 45] = _tag(UNIV, CONS, SET), 99 | [ 46] = _jump_target(95), 100 | [ 47] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // siSequence 101 | [ 48] = _tag(UNIV, CONS, SEQ), 102 | [ 49] = _jump_target(101), 103 | [ 50] = ASN1_OP_COND_FAIL, 104 | [ 51] = ASN1_OP_END_SEQ, 105 | [ 52] = ASN1_OP_END_SEQ, 106 | [ 53] = ASN1_OP_RETURN, 107 | 108 | // DigestAlgorithmIdentifier 109 | [ 54] = ASN1_OP_MATCH_JUMP, 110 | [ 55] = _tag(UNIV, CONS, SEQ), 111 | [ 56] = _jump_target(107), // --> DigestAlgorithmIdentifier 112 | [ 57] = ASN1_OP_END_SET_OF, 113 | [ 58] = _jump_target(54), 114 | [ 59] = ASN1_OP_RETURN, 115 | 116 | // DigestAlgorithmIdentifier 117 | [ 60] = ASN1_OP_MATCH_JUMP, 118 | [ 61] = _tag(UNIV, CONS, SEQ), 119 | [ 62] = _jump_target(107), // --> DigestAlgorithmIdentifier 120 | [ 63] = ASN1_OP_END_SEQ_OF, 121 | [ 64] = _jump_target(60), 122 | [ 65] = ASN1_OP_RETURN, 123 | 124 | // Data 125 | [ 66] = ASN1_OP_MATCH_ANY_ACT, 126 | [ 67] = _action(ACT_pkcs7_note_data), 127 | [ 68] = ASN1_OP_END_SEQ, 128 | [ 69] = ASN1_OP_RETURN, 129 | 130 | // ExtendedCertificateOrCertificate 131 | // Certificate 132 | [ 70] = ASN1_OP_MATCH_ANY_ACT_OR_SKIP, 133 | [ 71] = _action(ACT_pkcs7_extract_cert), 134 | // ExtendedCertificate 135 | // Certificate 136 | [ 72] = ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP, 137 | [ 73] = _action(ACT_pkcs7_extract_cert), 138 | [ 74] = ASN1_OP_COND_FAIL, 139 | [ 75] = ASN1_OP_END_SET_OF, 140 | [ 76] = _jump_target(70), 141 | [ 77] = ASN1_OP_RETURN, 142 | 143 | // Certificate 144 | [ 78] = ASN1_OP_MATCH_ANY_ACT, 145 | [ 79] = _action(ACT_pkcs7_extract_cert), 146 | [ 80] = ASN1_OP_END_SEQ_OF, 147 | [ 81] = _jump_target(78), 148 | [ 82] = ASN1_OP_RETURN, 149 | 150 | // CertificateList 151 | [ 83] = ASN1_OP_MATCH_JUMP, 152 | [ 84] = _tag(UNIV, CONS, SEQ), 153 | [ 85] = _jump_target(113), // --> CertificateList 154 | [ 86] = ASN1_OP_END_SET_OF, 155 | [ 87] = _jump_target(83), 156 | [ 88] = ASN1_OP_RETURN, 157 | 158 | // CertificateList 159 | [ 89] = ASN1_OP_MATCH_JUMP, 160 | [ 90] = _tag(UNIV, CONS, SEQ), 161 | [ 91] = _jump_target(113), // --> CertificateList 162 | [ 92] = ASN1_OP_END_SEQ_OF, 163 | [ 93] = _jump_target(89), 164 | [ 94] = ASN1_OP_RETURN, 165 | 166 | // SignerInfo 167 | [ 95] = ASN1_OP_MATCH_JUMP, 168 | [ 96] = _tag(UNIV, CONS, SEQ), 169 | [ 97] = _jump_target(118), // --> SignerInfo 170 | [ 98] = ASN1_OP_END_SET_OF, 171 | [ 99] = _jump_target(95), 172 | [ 100] = ASN1_OP_RETURN, 173 | 174 | // SignerInfo 175 | [ 101] = ASN1_OP_MATCH_JUMP, 176 | [ 102] = _tag(UNIV, CONS, SEQ), 177 | [ 103] = _jump_target(118), // --> SignerInfo 178 | [ 104] = ASN1_OP_END_SEQ_OF, 179 | [ 105] = _jump_target(101), 180 | [ 106] = ASN1_OP_RETURN, 181 | 182 | [ 107] = ASN1_OP_MATCH_ACT, // algorithm 183 | [ 108] = _tag(UNIV, PRIM, OID), 184 | [ 109] = _action(ACT_pkcs7_note_OID), 185 | [ 110] = ASN1_OP_MATCH_ANY_OR_SKIP, // parameters 186 | [ 111] = ASN1_OP_END_SEQ, 187 | [ 112] = ASN1_OP_RETURN, 188 | 189 | // Certificate 190 | [ 113] = ASN1_OP_MATCH_ANY_ACT, 191 | [ 114] = _action(ACT_pkcs7_extract_cert), 192 | [ 115] = ASN1_OP_END_SEQ_OF, 193 | [ 116] = _jump_target(113), 194 | [ 117] = ASN1_OP_RETURN, 195 | 196 | [ 118] = ASN1_OP_MATCH, // version 197 | [ 119] = _tag(UNIV, PRIM, INT), 198 | // IssuerAndSerialNumber 199 | [ 120] = ASN1_OP_MATCH, 200 | [ 121] = _tag(UNIV, CONS, SEQ), 201 | // Name 202 | [ 122] = ASN1_OP_MATCH, 203 | [ 123] = _tag(UNIV, CONS, SEQ), 204 | // RelativeDistinguishedName 205 | [ 124] = ASN1_OP_MATCH, 206 | [ 125] = _tag(UNIV, CONS, SET), 207 | // AttributeValueAssertion 208 | [ 126] = ASN1_OP_MATCH, 209 | [ 127] = _tag(UNIV, CONS, SEQ), 210 | [ 128] = ASN1_OP_MATCH_ACT, // attributeType 211 | [ 129] = _tag(UNIV, PRIM, OID), 212 | [ 130] = _action(ACT_pkcs7_note_OID), 213 | [ 131] = ASN1_OP_MATCH_ANY, // attributeValue 214 | [ 132] = ASN1_OP_END_SEQ, 215 | [ 133] = ASN1_OP_END_SET_OF, 216 | [ 134] = _jump_target(126), 217 | [ 135] = ASN1_OP_END_SEQ_OF, 218 | [ 136] = _jump_target(124), 219 | [ 137] = ASN1_OP_ACT, 220 | [ 138] = _action(ACT_pkcs7_sig_note_issuer), 221 | // CertificateSerialNumber 222 | [ 139] = ASN1_OP_MATCH, 223 | [ 140] = _tag(UNIV, PRIM, INT), 224 | [ 141] = ASN1_OP_ACT, 225 | [ 142] = _action(ACT_pkcs7_sig_note_serial), 226 | [ 143] = ASN1_OP_END_SEQ, 227 | // DigestAlgorithmIdentifier 228 | [ 144] = ASN1_OP_MATCH_JUMP, 229 | [ 145] = _tag(UNIV, CONS, SEQ), 230 | [ 146] = _jump_target(107), // --> DigestAlgorithmIdentifier 231 | [ 147] = ASN1_OP_ACT, 232 | [ 148] = _action(ACT_pkcs7_sig_note_digest_algo), 233 | // SetOfAuthenticatedAttribute 234 | [ 149] = ASN1_OP_MATCH_JUMP_OR_SKIP, // aaSet 235 | [ 150] = _tagn(CONT, CONS, 0), 236 | [ 151] = _jump_target(178), // --> SetOfAuthenticatedAttribute 237 | [ 152] = ASN1_OP_MAYBE_ACT, 238 | [ 153] = _action(ACT_pkcs7_sig_note_set_of_authattrs), 239 | [ 154] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // aaSequence 240 | [ 155] = _tagn(CONT, CONS, 2), 241 | [ 156] = _jump_target(184), 242 | // DigestEncryptionAlgorithmIdentifier 243 | [ 157] = ASN1_OP_MATCH, 244 | [ 158] = _tag(UNIV, CONS, SEQ), 245 | [ 159] = ASN1_OP_MATCH_ACT, // algorithm 246 | [ 160] = _tag(UNIV, PRIM, OID), 247 | [ 161] = _action(ACT_pkcs7_note_OID), 248 | [ 162] = ASN1_OP_MATCH_ANY_OR_SKIP, // parameters 249 | [ 163] = ASN1_OP_END_SEQ, 250 | [ 164] = ASN1_OP_ACT, 251 | [ 165] = _action(ACT_pkcs7_sig_note_pkey_algo), 252 | // EncryptedDigest 253 | [ 166] = ASN1_OP_MATCH_ACT, 254 | [ 167] = _tag(UNIV, PRIM, OTS), 255 | [ 168] = _action(ACT_pkcs7_sig_note_signature), 256 | [ 169] = ASN1_OP_MATCH_JUMP_OR_SKIP, // uaSet 257 | [ 170] = _tagn(CONT, CONS, 1), 258 | [ 171] = _jump_target(193), 259 | [ 172] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // uaSequence 260 | [ 173] = _tagn(CONT, CONS, 3), 261 | [ 174] = _jump_target(199), 262 | [ 175] = ASN1_OP_END_SEQ_ACT, 263 | [ 176] = _action(ACT_pkcs7_note_signed_info), 264 | [ 177] = ASN1_OP_RETURN, 265 | 266 | // AuthenticatedAttribute 267 | [ 178] = ASN1_OP_MATCH_JUMP, 268 | [ 179] = _tag(UNIV, CONS, SEQ), 269 | [ 180] = _jump_target(205), // --> AuthenticatedAttribute 270 | [ 181] = ASN1_OP_END_SET_OF, 271 | [ 182] = _jump_target(178), 272 | [ 183] = ASN1_OP_RETURN, 273 | 274 | [ 184] = ASN1_OP_MATCH, // aaSequence 275 | [ 185] = _tag(UNIV, CONS, SEQ), 276 | // AuthenticatedAttribute 277 | [ 186] = ASN1_OP_MATCH_JUMP, 278 | [ 187] = _tag(UNIV, CONS, SEQ), 279 | [ 188] = _jump_target(205), // --> AuthenticatedAttribute 280 | [ 189] = ASN1_OP_END_SEQ_OF, 281 | [ 190] = _jump_target(186), 282 | [ 191] = ASN1_OP_END_SEQ, 283 | [ 192] = ASN1_OP_RETURN, 284 | 285 | // UnauthenticatedAttribute 286 | [ 193] = ASN1_OP_MATCH_JUMP, 287 | [ 194] = _tag(UNIV, CONS, SEQ), 288 | [ 195] = _jump_target(216), // --> UnauthenticatedAttribute 289 | [ 196] = ASN1_OP_END_SET_OF, 290 | [ 197] = _jump_target(193), 291 | [ 198] = ASN1_OP_RETURN, 292 | 293 | // UnauthenticatedAttribute 294 | [ 199] = ASN1_OP_MATCH_JUMP, 295 | [ 200] = _tag(UNIV, CONS, SEQ), 296 | [ 201] = _jump_target(216), // --> UnauthenticatedAttribute 297 | [ 202] = ASN1_OP_END_SEQ_OF, 298 | [ 203] = _jump_target(199), 299 | [ 204] = ASN1_OP_RETURN, 300 | 301 | [ 205] = ASN1_OP_MATCH_ACT, // type 302 | [ 206] = _tag(UNIV, PRIM, OID), 303 | [ 207] = _action(ACT_pkcs7_note_OID), 304 | [ 208] = ASN1_OP_MATCH, // values 305 | [ 209] = _tag(UNIV, CONS, SET), 306 | [ 210] = ASN1_OP_MATCH_ANY_ACT, 307 | [ 211] = _action(ACT_pkcs7_sig_note_authenticated_attr), 308 | [ 212] = ASN1_OP_END_SET_OF, 309 | [ 213] = _jump_target(210), 310 | [ 214] = ASN1_OP_END_SEQ, 311 | [ 215] = ASN1_OP_RETURN, 312 | 313 | [ 216] = ASN1_OP_MATCH_ACT, // type 314 | [ 217] = _tag(UNIV, PRIM, OID), 315 | [ 218] = _action(ACT_pkcs7_note_OID), 316 | [ 219] = ASN1_OP_MATCH, // values 317 | [ 220] = _tag(UNIV, CONS, SET), 318 | [ 221] = ASN1_OP_MATCH_ANY, 319 | [ 222] = ASN1_OP_END_SET_OF, 320 | [ 223] = _jump_target(221), 321 | [ 224] = ASN1_OP_END_SEQ, 322 | [ 225] = ASN1_OP_RETURN, 323 | }; 324 | 325 | const struct asn1_decoder pkcs7_decoder = { 326 | .machine = pkcs7_machine, 327 | .machlen = sizeof(pkcs7_machine), 328 | .actions = pkcs7_action_table, 329 | }; 330 | -------------------------------------------------------------------------------- /asn/pkcs7-asn1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for pkcs7 5 | */ 6 | #include "asn1_decoder.h" 7 | 8 | extern const struct asn1_decoder pkcs7_decoder; 9 | 10 | extern int pkcs7_extract_cert(void *, size_t, unsigned char, const void *, size_t); 11 | extern int pkcs7_note_OID(void *, size_t, unsigned char, const void *, size_t); 12 | extern int pkcs7_note_certificate_list(void *, size_t, unsigned char, const void *, size_t); 13 | extern int pkcs7_note_data(void *, size_t, unsigned char, const void *, size_t); 14 | extern int pkcs7_note_signed_info(void *, size_t, unsigned char, const void *, size_t); 15 | extern int pkcs7_sig_note_authenticated_attr(void *, size_t, unsigned char, const void *, size_t); 16 | extern int pkcs7_sig_note_digest_algo(void *, size_t, unsigned char, const void *, size_t); 17 | extern int pkcs7_sig_note_issuer(void *, size_t, unsigned char, const void *, size_t); 18 | extern int pkcs7_sig_note_pkey_algo(void *, size_t, unsigned char, const void *, size_t); 19 | extern int pkcs7_sig_note_serial(void *, size_t, unsigned char, const void *, size_t); 20 | extern int pkcs7_sig_note_set_of_authattrs(void *, size_t, unsigned char, const void *, size_t); 21 | extern int pkcs7_sig_note_signature(void *, size_t, unsigned char, const void *, size_t); 22 | 23 | -------------------------------------------------------------------------------- /asn/pkcs7.h: -------------------------------------------------------------------------------- 1 | /* PKCS#7 crypto data parser 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | #ifndef __PKCS7_H__ 12 | #define __PKCS7_H__ 13 | 14 | #include "misc.h" 15 | 16 | struct key; 17 | struct pkcs7_message; 18 | 19 | /* 20 | * pkcs7_parser.c 21 | */ 22 | extern struct pkcs7_message *pkcs7_parse_message(const void *data, 23 | size_t datalen); 24 | extern void pkcs7_free_message(struct pkcs7_message *pkcs7); 25 | 26 | extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, 27 | const void **_data, size_t *_datalen, 28 | bool want_wrapper); 29 | 30 | /* 31 | * pkcs7_trust.c 32 | */ 33 | extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7, 34 | struct key *trust_keyring, 35 | bool *_trusted); 36 | 37 | /* 38 | * pkcs7_verify.c 39 | */ 40 | extern int pkcs7_verify(struct pkcs7_message *pkcs7); 41 | 42 | #endif //__PKCS7_H__ 43 | -------------------------------------------------------------------------------- /asn/pkcs7_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #ifdef KLEE 9 | #include 10 | #endif 11 | 12 | #include "pkcs7_parser.h" 13 | #include "misc.h" 14 | 15 | #ifdef KLEE 16 | #define FUZZ_BUFFER_SIZE 1024 17 | #elif defined(KLEE_DEBUG) 18 | #define FUZZ_BUFFER_SIZE 1024 19 | #else 20 | #define FUZZ_BUFFER_SIZE (2*1024*1024) 21 | #endif 22 | 23 | int main(int argc, char **argv) 24 | { 25 | struct pkcs7_message * msg; 26 | char * fuzz_filename; 27 | int fuzz_length; 28 | char * fuzz_buffer; 29 | 30 | fuzz_buffer = malloc(FUZZ_BUFFER_SIZE); 31 | if(!fuzz_buffer) { 32 | printf("Failed to allocate fuzz buffer\n"); 33 | return 1; 34 | } 35 | pr_debug("fuzz_buffer %p\n", fuzz_buffer); 36 | 37 | #ifndef KLEE 38 | if(argc < 2) { 39 | printf("Usage: pkcs7 filename\n"); 40 | return 1; 41 | } 42 | fuzz_filename = argv[1]; 43 | #endif 44 | 45 | #ifdef __AFL_HAVE_MANUAL_CONTROL 46 | __AFL_INIT(); 47 | #endif 48 | 49 | #ifdef __AFL_LOOP 50 | while (__AFL_LOOP(1000)) { 51 | #endif 52 | 53 | memset(fuzz_buffer, 0, FUZZ_BUFFER_SIZE); 54 | 55 | #ifdef KLEE 56 | unsigned short size; 57 | klee_make_symbolic(&size, sizeof(short), "size"); 58 | size &= 0x3ff; 59 | 60 | klee_assume(size < FUZZ_BUFFER_SIZE); 61 | fuzz_length = size; 62 | if(fuzz_length == 0) 63 | return 1; 64 | 65 | klee_make_symbolic(fuzz_buffer, FUZZ_BUFFER_SIZE, "buffer"); 66 | 67 | #else 68 | 69 | fuzz_length = read_file(fuzz_filename, fuzz_buffer, FUZZ_BUFFER_SIZE); 70 | if(fuzz_length < 0) 71 | #ifdef __AFL_LOOP 72 | continue; 73 | #else 74 | return 1; 75 | #endif 76 | 77 | #endif 78 | 79 | msg = pkcs7_parse_message(fuzz_buffer, fuzz_length); 80 | if(!IS_ERR(msg)) 81 | pkcs7_free_message(msg); 82 | 83 | #ifdef __AFL_LOOP 84 | } 85 | #endif 86 | 87 | free(fuzz_buffer); 88 | 89 | return 0; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /asn/pkcs7_parser.c: -------------------------------------------------------------------------------- 1 | /* PKCS#7 parser 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "pkcs7_parser.h" 20 | #include "pkcs7-asn1.h" 21 | #include "oid_registry.h" 22 | #include "misc.h" 23 | 24 | struct pkcs7_parse_context { 25 | struct pkcs7_message *msg; /* Message being constructed */ 26 | struct pkcs7_signed_info *sinfo; /* SignedInfo being constructed */ 27 | struct pkcs7_signed_info **ppsinfo; 28 | struct x509_certificate *certs; /* Certificate cache */ 29 | struct x509_certificate **ppcerts; 30 | unsigned long data; /* Start of data */ 31 | enum OID last_oid; /* Last OID encountered */ 32 | unsigned x509_index; 33 | unsigned sinfo_index; 34 | }; 35 | 36 | /* 37 | * Free a signed information block. 38 | */ 39 | static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) 40 | { 41 | if (sinfo) { 42 | //mpi_free(sinfo->sig.mpi[0]); 43 | //free(sinfo->sig.digest); 44 | free(sinfo); 45 | } 46 | } 47 | 48 | /** 49 | * pkcs7_free_message - Free a PKCS#7 message 50 | * @pkcs7: The PKCS#7 message to free 51 | */ 52 | void pkcs7_free_message(struct pkcs7_message *pkcs7) 53 | { 54 | struct x509_certificate *cert; 55 | struct pkcs7_signed_info *sinfo; 56 | 57 | if (pkcs7) { 58 | while (pkcs7->certs) { 59 | cert = pkcs7->certs; 60 | pkcs7->certs = cert->next; 61 | x509_free_certificate(cert); 62 | } 63 | while (pkcs7->crl) { 64 | cert = pkcs7->crl; 65 | pkcs7->crl = cert->next; 66 | x509_free_certificate(cert); 67 | } 68 | while (pkcs7->signed_infos) { 69 | sinfo = pkcs7->signed_infos; 70 | pkcs7->signed_infos = sinfo->next; 71 | pkcs7_free_signed_info(sinfo); 72 | } 73 | free(pkcs7); 74 | } 75 | } 76 | 77 | /** 78 | * pkcs7_parse_message - Parse a PKCS#7 message 79 | * @data: The raw binary ASN.1 encoded message to be parsed 80 | * @datalen: The size of the encoded message 81 | */ 82 | struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) 83 | { 84 | struct pkcs7_parse_context *ctx; 85 | struct pkcs7_message *msg = ERR_PTR(-ENOMEM); 86 | int ret; 87 | 88 | ctx = calloc(1, sizeof(struct pkcs7_parse_context)); 89 | if (!ctx) 90 | goto out_no_ctx; 91 | ctx->msg = calloc(1, sizeof(struct pkcs7_message)); 92 | if (!ctx->msg) 93 | goto out_no_msg; 94 | ctx->sinfo = calloc(1, sizeof(struct pkcs7_signed_info)); 95 | if (!ctx->sinfo) 96 | goto out_no_sinfo; 97 | 98 | ctx->data = (unsigned long)data; 99 | ctx->ppcerts = &ctx->certs; 100 | ctx->ppsinfo = &ctx->msg->signed_infos; 101 | 102 | /* Attempt to decode the signature */ 103 | ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); 104 | if (ret < 0) { 105 | msg = ERR_PTR(ret); 106 | goto out; 107 | } 108 | 109 | msg = ctx->msg; 110 | ctx->msg = NULL; 111 | 112 | out: 113 | while (ctx->certs) { 114 | struct x509_certificate *cert = ctx->certs; 115 | ctx->certs = cert->next; 116 | x509_free_certificate(cert); 117 | } 118 | pkcs7_free_signed_info(ctx->sinfo); 119 | out_no_sinfo: 120 | pkcs7_free_message(ctx->msg); 121 | out_no_msg: 122 | free(ctx); 123 | out_no_ctx: 124 | return msg; 125 | } 126 | 127 | /** 128 | * pkcs7_get_content_data - Get access to the PKCS#7 content 129 | * @pkcs7: The preparsed PKCS#7 message to access 130 | * @_data: Place to return a pointer to the data 131 | * @_data_len: Place to return the data length 132 | * @want_wrapper: True if the ASN.1 object header should be included in the data 133 | * 134 | * Get access to the data content of the PKCS#7 message, including, optionally, 135 | * the header of the ASN.1 object that contains it. Returns -ENODATA if the 136 | * data object was missing from the message. 137 | */ 138 | int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, 139 | const void **_data, size_t *_data_len, 140 | bool want_wrapper) 141 | { 142 | size_t wrapper; 143 | 144 | if (!pkcs7->data) 145 | return -ENODATA; 146 | 147 | wrapper = want_wrapper ? pkcs7->data_hdrlen : 0; 148 | *_data = pkcs7->data - wrapper; 149 | *_data_len = pkcs7->data_len + wrapper; 150 | return 0; 151 | } 152 | 153 | /* 154 | * Note an OID when we find one for later processing when we know how 155 | * to interpret it. 156 | */ 157 | int pkcs7_note_OID(void *context, size_t hdrlen, 158 | unsigned char tag, 159 | const void *value, size_t vlen) 160 | { 161 | struct pkcs7_parse_context *ctx = context; 162 | 163 | ctx->last_oid = look_up_OID(value, vlen); 164 | if (ctx->last_oid == OID__NR) { 165 | char buffer[50]; 166 | sprint_oid(value, vlen, buffer, sizeof(buffer)); 167 | printk("PKCS7: Unknown OID: [%lu] %s\n", 168 | (unsigned long)value - ctx->data, buffer); 169 | } 170 | return 0; 171 | } 172 | 173 | /* 174 | * Note the digest algorithm for the signature. 175 | */ 176 | int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, 177 | unsigned char tag, 178 | const void *value, size_t vlen) 179 | { 180 | struct pkcs7_parse_context *ctx = context; 181 | 182 | switch (ctx->last_oid) { 183 | case OID_md4: 184 | //ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4; 185 | printk("Digest algo: MD4\n"); 186 | break; 187 | case OID_md5: 188 | //ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5; 189 | printk("Digest algo: MD5\n"); 190 | break; 191 | case OID_sha1: 192 | //ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1; 193 | printk("Digest algo: SHA1\n"); 194 | break; 195 | case OID_sha256: 196 | //ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256; 197 | printk("Digest algo: SHA256\n"); 198 | break; 199 | default: 200 | printk("Unsupported digest algo: %u\n", ctx->last_oid); 201 | return -ENOPKG; 202 | } 203 | return 0; 204 | } 205 | 206 | /* 207 | * Note the public key algorithm for the signature. 208 | */ 209 | int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, 210 | unsigned char tag, 211 | const void *value, size_t vlen) 212 | { 213 | struct pkcs7_parse_context *ctx = context; 214 | 215 | switch (ctx->last_oid) { 216 | case OID_rsaEncryption: 217 | //ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA; 218 | printk("Pkey algo: RSA\n"); 219 | break; 220 | default: 221 | printk("Unsupported pkey algo: %u\n", ctx->last_oid); 222 | return -ENOPKG; 223 | } 224 | return 0; 225 | } 226 | 227 | /* 228 | * Extract a certificate and store it in the context. 229 | */ 230 | int pkcs7_extract_cert(void *context, size_t hdrlen, 231 | unsigned char tag, 232 | const void *value, size_t vlen) 233 | { 234 | struct pkcs7_parse_context *ctx = context; 235 | struct x509_certificate *x509; 236 | 237 | if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) { 238 | pr_debug("Cert began with tag %02x at %lu\n", 239 | tag, (unsigned long)ctx - ctx->data); 240 | return -EBADMSG; 241 | } 242 | 243 | /* We have to correct for the header so that the X.509 parser can start 244 | * from the beginning. Note that since X.509 stipulates DER, there 245 | * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which 246 | * stipulates BER). 247 | */ 248 | value -= hdrlen; 249 | vlen += hdrlen; 250 | 251 | if (((u8*)value)[1] == 0x80) 252 | vlen += 2; /* Indefinite length - there should be an EOC */ 253 | 254 | x509 = x509_cert_parse(value, vlen); 255 | if (IS_ERR(x509)) 256 | return PTR_ERR(x509); 257 | 258 | pr_debug("Got cert for %s\n", x509->subject); 259 | pr_debug("- fingerprint %s\n", x509->fingerprint); 260 | 261 | x509->index = ++ctx->x509_index; 262 | *ctx->ppcerts = x509; 263 | ctx->ppcerts = &x509->next; 264 | return 0; 265 | } 266 | 267 | /* 268 | * Save the certificate list 269 | */ 270 | int pkcs7_note_certificate_list(void *context, size_t hdrlen, 271 | unsigned char tag, 272 | const void *value, size_t vlen) 273 | { 274 | struct pkcs7_parse_context *ctx = context; 275 | 276 | pr_devel("Got cert list (%02x)\n", tag); 277 | 278 | *ctx->ppcerts = ctx->msg->certs; 279 | ctx->msg->certs = ctx->certs; 280 | ctx->certs = NULL; 281 | ctx->ppcerts = &ctx->certs; 282 | return 0; 283 | } 284 | 285 | /* 286 | * Extract the data from the message and store that and its content type OID in 287 | * the context. 288 | */ 289 | int pkcs7_note_data(void *context, size_t hdrlen, 290 | unsigned char tag, 291 | const void *value, size_t vlen) 292 | { 293 | struct pkcs7_parse_context *ctx = context; 294 | 295 | pr_debug("Got data\n"); 296 | 297 | ctx->msg->data = value; 298 | ctx->msg->data_len = vlen; 299 | ctx->msg->data_hdrlen = hdrlen; 300 | ctx->msg->data_type = ctx->last_oid; 301 | return 0; 302 | } 303 | 304 | /* 305 | * Parse authenticated attributes 306 | */ 307 | int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, 308 | unsigned char tag, 309 | const void *value, size_t vlen) 310 | { 311 | struct pkcs7_parse_context *ctx = context; 312 | 313 | pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 314 | 315 | switch (ctx->last_oid) { 316 | case OID_messageDigest: 317 | if (tag != ASN1_OTS) 318 | return -EBADMSG; 319 | ctx->sinfo->msgdigest = value; 320 | ctx->sinfo->msgdigest_len = vlen; 321 | return 0; 322 | default: 323 | return 0; 324 | } 325 | } 326 | 327 | /* 328 | * Note the set of auth attributes for digestion purposes [RFC2315 9.3] 329 | */ 330 | int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, 331 | unsigned char tag, 332 | const void *value, size_t vlen) 333 | { 334 | struct pkcs7_parse_context *ctx = context; 335 | 336 | /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ 337 | ctx->sinfo->authattrs = value - (hdrlen - 1); 338 | ctx->sinfo->authattrs_len = vlen + (hdrlen - 1); 339 | return 0; 340 | } 341 | 342 | /* 343 | * Note the issuing certificate serial number 344 | */ 345 | int pkcs7_sig_note_serial(void *context, size_t hdrlen, 346 | unsigned char tag, 347 | const void *value, size_t vlen) 348 | { 349 | struct pkcs7_parse_context *ctx = context; 350 | ctx->sinfo->raw_serial = value; 351 | ctx->sinfo->raw_serial_size = vlen; 352 | return 0; 353 | } 354 | 355 | /* 356 | * Note the issuer's name 357 | */ 358 | int pkcs7_sig_note_issuer(void *context, size_t hdrlen, 359 | unsigned char tag, 360 | const void *value, size_t vlen) 361 | { 362 | struct pkcs7_parse_context *ctx = context; 363 | ctx->sinfo->raw_issuer = value; 364 | ctx->sinfo->raw_issuer_size = vlen; 365 | return 0; 366 | } 367 | 368 | /* 369 | * Note the signature data 370 | */ 371 | int pkcs7_sig_note_signature(void *context, size_t hdrlen, 372 | unsigned char tag, 373 | const void *value, size_t vlen) 374 | { 375 | //We don't actually care about getting the key here 376 | //and trying to compile in the MPI library is too much work 377 | #if 0 378 | struct pkcs7_parse_context *ctx = context; 379 | MPI mpi; 380 | 381 | BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA); 382 | 383 | mpi = mpi_read_raw_data(value, vlen); 384 | if (!mpi) 385 | return -ENOMEM; 386 | 387 | ctx->sinfo->sig.mpi[0] = mpi; 388 | ctx->sinfo->sig.nr_mpi = 1; 389 | #endif 390 | return 0; 391 | } 392 | 393 | /* 394 | * Note a signature information block 395 | */ 396 | int pkcs7_note_signed_info(void *context, size_t hdrlen, 397 | unsigned char tag, 398 | const void *value, size_t vlen) 399 | { 400 | struct pkcs7_parse_context *ctx = context; 401 | 402 | ctx->sinfo->index = ++ctx->sinfo_index; 403 | *ctx->ppsinfo = ctx->sinfo; 404 | ctx->ppsinfo = &ctx->sinfo->next; 405 | ctx->sinfo = calloc(1, sizeof(struct pkcs7_signed_info)); 406 | if (!ctx->sinfo) 407 | return -ENOMEM; 408 | return 0; 409 | } 410 | -------------------------------------------------------------------------------- /asn/pkcs7_parser.h: -------------------------------------------------------------------------------- 1 | /* PKCS#7 crypto data parser internal definitions 2 | * 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 | * Written by David Howells (dhowells@redhat.com) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public Licence 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the Licence, or (at your option) any later version. 10 | */ 11 | 12 | #ifndef __PKCS7_PARSER_H__ 13 | #define __PKCS7_PARSER_H__ 14 | 15 | #include "misc.h" 16 | 17 | #include "oid_registry.h" 18 | #include "pkcs7.h" 19 | #include "x509_cert.h" 20 | 21 | #define kenter(FMT, ...) \ 22 | pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) 23 | #define kleave(FMT, ...) \ 24 | pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) 25 | 26 | struct pkcs7_signed_info { 27 | struct pkcs7_signed_info *next; 28 | struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ 29 | unsigned index; 30 | bool trusted; 31 | bool unsupported_crypto; /* T if not usable due to missing crypto */ 32 | 33 | /* Message digest - the digest of the Content Data (or NULL) */ 34 | const void *msgdigest; 35 | unsigned msgdigest_len; 36 | 37 | /* Authenticated Attribute data (or NULL) */ 38 | unsigned authattrs_len; 39 | const void *authattrs; 40 | 41 | /* Issuing cert serial number and issuer's name */ 42 | const void *raw_serial; 43 | unsigned raw_serial_size; 44 | unsigned raw_issuer_size; 45 | const void *raw_issuer; 46 | 47 | /* Message signature. 48 | * 49 | * This contains the generated digest of _either_ the Content Data or 50 | * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of 51 | * the attributes contains the digest of the the Content Data within 52 | * it. 53 | */ 54 | //struct public_key_signature sig; 55 | }; 56 | 57 | struct pkcs7_message { 58 | struct x509_certificate *certs; /* Certificate list */ 59 | struct x509_certificate *crl; /* Revocation list */ 60 | struct pkcs7_signed_info *signed_infos; 61 | 62 | /* Content Data (or NULL) */ 63 | enum OID data_type; /* Type of Data */ 64 | size_t data_len; /* Length of Data */ 65 | size_t data_hdrlen; /* Length of Data ASN.1 header */ 66 | const void *data; /* Content Data (or 0) */ 67 | }; 68 | 69 | struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen); 70 | void pkcs7_free_message(struct pkcs7_message *pkcs7); 71 | 72 | #endif //__PKCS7_PARSER_H__ 73 | -------------------------------------------------------------------------------- /asn/pkcs7_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define BUFFER_SIZE (1024*1024) 12 | 13 | int read_file(char * filename, char *buffer, long length) 14 | { 15 | FILE *fp; 16 | long fsize, total = 0, num_read; 17 | 18 | fp = fopen(filename, "rb"); 19 | if (!fp) 20 | return -1; 21 | 22 | //Get the size 23 | fseek(fp, 0, SEEK_END); 24 | fsize = ftell(fp); 25 | fseek(fp, 0, SEEK_SET); 26 | 27 | if(fsize > length) 28 | fsize = length; 29 | 30 | while (total < fsize) 31 | { 32 | num_read = fread(buffer + total, 1, fsize, fp); 33 | total += num_read; 34 | } 35 | 36 | fclose(fp); 37 | 38 | return fsize; 39 | } 40 | 41 | int main(int argc, char ** argv) 42 | { 43 | unsigned char buffer[BUFFER_SIZE]; 44 | int length; 45 | 46 | length = read_file(argv[1], buffer, BUFFER_SIZE); 47 | if(length < 0) { 48 | printf("Couldn't read %s\n", argv[1]); 49 | return 1; 50 | } 51 | 52 | syscall(__NR_add_key, "pkcs7_test", NULL, buffer, length, KEY_SPEC_SESSION_KEYRING); 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /asn/rsa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RSA internal helpers 3 | * 4 | * Copyright (c) 2015, Intel Corporation 5 | * Authors: Tadeusz Struk 6 | * 7 | * This program is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU General Public License as published by the Free 9 | * Software Foundation; either version 2 of the License, or (at your option) 10 | * any later version. 11 | * 12 | */ 13 | #ifndef _RSA_HELPER_ 14 | #define _RSA_HELPER_ 15 | 16 | #include "misc.h" 17 | 18 | /** 19 | * rsa_key - RSA key structure 20 | * @n : RSA modulus raw byte stream 21 | * @e : RSA public exponent raw byte stream 22 | * @d : RSA private exponent raw byte stream 23 | * @p : RSA prime factor p of n raw byte stream 24 | * @q : RSA prime factor q of n raw byte stream 25 | * @dp : RSA exponent d mod (p - 1) raw byte stream 26 | * @dq : RSA exponent d mod (q - 1) raw byte stream 27 | * @qinv : RSA CRT coefficient q^(-1) mod p raw byte stream 28 | * @n_sz : length in bytes of RSA modulus n 29 | * @e_sz : length in bytes of RSA public exponent 30 | * @d_sz : length in bytes of RSA private exponent 31 | * @p_sz : length in bytes of p field 32 | * @q_sz : length in bytes of q field 33 | * @dp_sz : length in bytes of dp field 34 | * @dq_sz : length in bytes of dq field 35 | * @qinv_sz : length in bytes of qinv field 36 | */ 37 | struct rsa_key { 38 | const u8 *n; 39 | const u8 *e; 40 | const u8 *d; 41 | const u8 *p; 42 | const u8 *q; 43 | const u8 *dp; 44 | const u8 *dq; 45 | const u8 *qinv; 46 | size_t n_sz; 47 | size_t e_sz; 48 | size_t d_sz; 49 | size_t p_sz; 50 | size_t q_sz; 51 | size_t dp_sz; 52 | size_t dq_sz; 53 | size_t qinv_sz; 54 | }; 55 | 56 | int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, 57 | unsigned int key_len); 58 | 59 | int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key, 60 | unsigned int key_len); 61 | 62 | //extern struct crypto_template rsa_pkcs1pad_tmpl; 63 | #endif 64 | -------------------------------------------------------------------------------- /asn/rsa_helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RSA key extract helper 3 | * 4 | * Copyright (c) 2015, Intel Corporation 5 | * Authors: Tadeusz Struk 6 | * 7 | * This program is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU General Public License as published by the Free 9 | * Software Foundation; either version 2 of the License, or (at your option) 10 | * any later version. 11 | * 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "rsa.h" 20 | #include "rsapubkey-asn1.h" 21 | #include "rsaprivkey-asn1.h" 22 | 23 | int rsa_get_n(void *context, size_t hdrlen, unsigned char tag, 24 | const void *value, size_t vlen) 25 | { 26 | struct rsa_key *key = context; 27 | const u8 *ptr = value; 28 | size_t n_sz = vlen; 29 | 30 | pr_debug("rsa_get_n %p %lu\n", value, vlen); 31 | 32 | /* invalid key provided */ 33 | if (!value || !vlen) 34 | return -EINVAL; 35 | 36 | if (fips_enabled) { 37 | while (!*ptr && n_sz) { 38 | ptr++; 39 | n_sz--; 40 | } 41 | 42 | /* In FIPS mode only allow key size 2K and higher */ 43 | if (n_sz < 256) { 44 | pr_err("RSA: key size not allowed in FIPS mode\n"); 45 | return -EINVAL; 46 | } 47 | } 48 | 49 | key->n = value; 50 | key->n_sz = vlen; 51 | 52 | return 0; 53 | } 54 | 55 | int rsa_get_e(void *context, size_t hdrlen, unsigned char tag, 56 | const void *value, size_t vlen) 57 | { 58 | struct rsa_key *key = context; 59 | 60 | pr_debug("rsa_get_e %p %lu\n", value, vlen); 61 | 62 | /* invalid key provided */ 63 | if (!value || !key->n_sz || !vlen || vlen > key->n_sz) 64 | return -EINVAL; 65 | 66 | key->e = value; 67 | key->e_sz = vlen; 68 | 69 | return 0; 70 | } 71 | 72 | int rsa_get_d(void *context, size_t hdrlen, unsigned char tag, 73 | const void *value, size_t vlen) 74 | { 75 | struct rsa_key *key = context; 76 | 77 | pr_debug("rsa_get_d %p %lu\n", value, vlen); 78 | 79 | /* invalid key provided */ 80 | if (!value || !key->n_sz || !vlen || vlen > key->n_sz) 81 | return -EINVAL; 82 | 83 | key->d = value; 84 | key->d_sz = vlen; 85 | 86 | return 0; 87 | } 88 | 89 | int rsa_get_p(void *context, size_t hdrlen, unsigned char tag, 90 | const void *value, size_t vlen) 91 | { 92 | struct rsa_key *key = context; 93 | 94 | pr_debug("rsa_get_p %p %lu\n", value, vlen); 95 | 96 | /* invalid key provided */ 97 | if (!value || !vlen || vlen > key->n_sz) 98 | return -EINVAL; 99 | 100 | key->p = value; 101 | key->p_sz = vlen; 102 | 103 | return 0; 104 | } 105 | 106 | int rsa_get_q(void *context, size_t hdrlen, unsigned char tag, 107 | const void *value, size_t vlen) 108 | { 109 | struct rsa_key *key = context; 110 | 111 | pr_debug("rsa_get_q %p %lu\n", value, vlen); 112 | 113 | /* invalid key provided */ 114 | if (!value || !vlen || vlen > key->n_sz) 115 | return -EINVAL; 116 | 117 | key->q = value; 118 | key->q_sz = vlen; 119 | 120 | return 0; 121 | } 122 | 123 | int rsa_get_dp(void *context, size_t hdrlen, unsigned char tag, 124 | const void *value, size_t vlen) 125 | { 126 | struct rsa_key *key = context; 127 | 128 | pr_debug("rsa_get_dp %p %lu\n", value, vlen); 129 | 130 | /* invalid key provided */ 131 | if (!value || !vlen || vlen > key->n_sz) 132 | return -EINVAL; 133 | 134 | key->dp = value; 135 | key->dp_sz = vlen; 136 | 137 | return 0; 138 | } 139 | 140 | int rsa_get_dq(void *context, size_t hdrlen, unsigned char tag, 141 | const void *value, size_t vlen) 142 | { 143 | struct rsa_key *key = context; 144 | 145 | pr_debug("rsa_get_dq %p %lu\n", value, vlen); 146 | 147 | /* invalid key provided */ 148 | if (!value || !vlen || vlen > key->n_sz) 149 | return -EINVAL; 150 | 151 | key->dq = value; 152 | key->dq_sz = vlen; 153 | 154 | return 0; 155 | } 156 | 157 | int rsa_get_qinv(void *context, size_t hdrlen, unsigned char tag, 158 | const void *value, size_t vlen) 159 | { 160 | struct rsa_key *key = context; 161 | 162 | pr_debug("rsa_get_qinv %p %lu\n", value, vlen); 163 | 164 | /* invalid key provided */ 165 | if (!value || !vlen || vlen > key->n_sz) 166 | return -EINVAL; 167 | 168 | key->qinv = value; 169 | key->qinv_sz = vlen; 170 | 171 | return 0; 172 | } 173 | 174 | /** 175 | * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in the 176 | * provided struct rsa_key, pointers to the raw key as is, 177 | * so that the caller can copy it or MPI parse it, etc. 178 | * 179 | * @rsa_key: struct rsa_key key representation 180 | * @key: key in BER format 181 | * @key_len: length of key 182 | * 183 | * Return: 0 on success or error code in case of error 184 | */ 185 | int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, 186 | unsigned int key_len) 187 | { 188 | return asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len); 189 | } 190 | 191 | /** 192 | * rsa_parse_priv_key() - decodes the BER encoded buffer and stores in the 193 | * provided struct rsa_key, pointers to the raw key 194 | * as is, so that the caller can copy it or MPI parse it, 195 | * etc. 196 | * 197 | * @rsa_key: struct rsa_key key representation 198 | * @key: key in BER format 199 | * @key_len: length of key 200 | * 201 | * Return: 0 on success or error code in case of error 202 | */ 203 | int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key, 204 | unsigned int key_len) 205 | { 206 | return asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len); 207 | } 208 | 209 | -------------------------------------------------------------------------------- /asn/rsa_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #ifdef KLEE 10 | #include 11 | #endif 12 | 13 | #include "rsa.h" 14 | #include "misc.h" 15 | 16 | #ifdef KLEE 17 | #define FUZZ_BUFFER_SIZE 1024 18 | #elif defined(KLEE_DEBUG) 19 | #define FUZZ_BUFFER_SIZE 1024 20 | #else 21 | #define FUZZ_BUFFER_SIZE (50*1024) 22 | #endif 23 | 24 | int main(int argc, char **argv) 25 | { 26 | struct rsa_key key; 27 | char * fuzz_filename; 28 | int ret, fuzz_length; 29 | u8 * fuzz_buffer; 30 | 31 | fuzz_buffer = malloc(FUZZ_BUFFER_SIZE); 32 | if(!fuzz_buffer) { 33 | printf("Failed to allocate fuzz buffer\n"); 34 | return 1; 35 | } 36 | pr_debug("fuzz_buffer %p\n", fuzz_buffer); 37 | 38 | #ifndef KLEE 39 | if(argc < 2) { 40 | printf("Usage: rsa filename\n"); 41 | return 1; 42 | } 43 | fuzz_filename = argv[1]; 44 | #endif 45 | 46 | #ifdef __AFL_HAVE_MANUAL_CONTROL 47 | __AFL_INIT(); 48 | #endif 49 | 50 | #ifdef __AFL_LOOP 51 | while (__AFL_LOOP(1000)) { 52 | #endif 53 | 54 | memset(fuzz_buffer, 0, FUZZ_BUFFER_SIZE); 55 | 56 | #ifdef KLEE 57 | unsigned short size; 58 | klee_make_symbolic(&size, sizeof(short), "size"); 59 | size &= 0x3ff; 60 | 61 | klee_assume(size < FUZZ_BUFFER_SIZE); 62 | fuzz_length = size; 63 | if(fuzz_length == 0) 64 | return 1; 65 | 66 | klee_make_symbolic(fuzz_buffer, FUZZ_BUFFER_SIZE, "buffer"); 67 | 68 | #else 69 | 70 | fuzz_length = read_file(fuzz_filename, fuzz_buffer, FUZZ_BUFFER_SIZE); 71 | if(fuzz_length < 0) 72 | #ifdef __AFL_LOOP 73 | continue; 74 | #else 75 | return 1; 76 | #endif 77 | 78 | #endif 79 | 80 | memset(&key, 0, sizeof(key)); 81 | #ifdef RSA_PUB_KEY 82 | ret = rsa_parse_priv_key(&key, fuzz_buffer, fuzz_length); 83 | #else 84 | ret = rsa_parse_pub_key(&key, fuzz_buffer, fuzz_length); 85 | #endif 86 | pr_debug("Key parsed, ret = %d\n", ret); 87 | 88 | if(!ret) { 89 | //If parsing succeeded, make sure the key pointers are within the buffer given 90 | if(key.n) assert(key.n >= fuzz_buffer && (key.n + key.n_sz) <= fuzz_buffer + fuzz_length); 91 | if(key.e) assert(key.e >= fuzz_buffer && (key.e + key.e_sz) <= fuzz_buffer + fuzz_length); 92 | if(key.d) assert(key.d >= fuzz_buffer && (key.d + key.d_sz) <= fuzz_buffer + fuzz_length); 93 | if(key.p) assert(key.p >= fuzz_buffer && (key.p + key.p_sz) <= fuzz_buffer + fuzz_length); 94 | if(key.q) assert(key.q >= fuzz_buffer && (key.q + key.q_sz) <= fuzz_buffer + fuzz_length); 95 | if(key.dp) assert(key.dp >= fuzz_buffer && (key.dp + key.dp_sz) <= fuzz_buffer + fuzz_length); 96 | if(key.dq) assert(key.dq >= fuzz_buffer && (key.dq + key.dq_sz) <= fuzz_buffer + fuzz_length); 97 | if(key.qinv) assert(key.qinv >= fuzz_buffer && (key.qinv + key.qinv_sz) <= fuzz_buffer + fuzz_length); 98 | } 99 | 100 | #ifdef __AFL_LOOP 101 | } 102 | #endif 103 | 104 | free(fuzz_buffer); 105 | 106 | return 0; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /asn/rsaprivkey-asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for rsaprivkey 5 | */ 6 | #include "asn1_ber_bytecode.h" 7 | #include "rsaprivkey-asn1.h" 8 | 9 | enum rsaprivkey_actions { 10 | ACT_rsa_get_d = 0, 11 | ACT_rsa_get_dp = 1, 12 | ACT_rsa_get_dq = 2, 13 | ACT_rsa_get_e = 3, 14 | ACT_rsa_get_n = 4, 15 | ACT_rsa_get_p = 5, 16 | ACT_rsa_get_q = 6, 17 | ACT_rsa_get_qinv = 7, 18 | NR__rsaprivkey_actions = 8 19 | }; 20 | 21 | static const asn1_action_t rsaprivkey_action_table[NR__rsaprivkey_actions] = { 22 | [ 0] = rsa_get_d, 23 | [ 1] = rsa_get_dp, 24 | [ 2] = rsa_get_dq, 25 | [ 3] = rsa_get_e, 26 | [ 4] = rsa_get_n, 27 | [ 5] = rsa_get_p, 28 | [ 6] = rsa_get_q, 29 | [ 7] = rsa_get_qinv, 30 | }; 31 | 32 | static const unsigned char rsaprivkey_machine[] = { 33 | // RsaPrivKey 34 | [ 0] = ASN1_OP_MATCH, 35 | [ 1] = _tag(UNIV, CONS, SEQ), 36 | [ 2] = ASN1_OP_MATCH, // version 37 | [ 3] = _tag(UNIV, PRIM, INT), 38 | [ 4] = ASN1_OP_MATCH_ACT, // n 39 | [ 5] = _tag(UNIV, PRIM, INT), 40 | [ 6] = _action(ACT_rsa_get_n), 41 | [ 7] = ASN1_OP_MATCH_ACT, // e 42 | [ 8] = _tag(UNIV, PRIM, INT), 43 | [ 9] = _action(ACT_rsa_get_e), 44 | [ 10] = ASN1_OP_MATCH_ACT, // d 45 | [ 11] = _tag(UNIV, PRIM, INT), 46 | [ 12] = _action(ACT_rsa_get_d), 47 | [ 13] = ASN1_OP_MATCH_ACT, // prime1 48 | [ 14] = _tag(UNIV, PRIM, INT), 49 | [ 15] = _action(ACT_rsa_get_p), 50 | [ 16] = ASN1_OP_MATCH_ACT, // prime2 51 | [ 17] = _tag(UNIV, PRIM, INT), 52 | [ 18] = _action(ACT_rsa_get_q), 53 | [ 19] = ASN1_OP_MATCH_ACT, // exponent1 54 | [ 20] = _tag(UNIV, PRIM, INT), 55 | [ 21] = _action(ACT_rsa_get_dp), 56 | [ 22] = ASN1_OP_MATCH_ACT, // exponent2 57 | [ 23] = _tag(UNIV, PRIM, INT), 58 | [ 24] = _action(ACT_rsa_get_dq), 59 | [ 25] = ASN1_OP_MATCH_ACT, // coefficient 60 | [ 26] = _tag(UNIV, PRIM, INT), 61 | [ 27] = _action(ACT_rsa_get_qinv), 62 | [ 28] = ASN1_OP_END_SEQ, 63 | [ 29] = ASN1_OP_COMPLETE, 64 | }; 65 | 66 | const struct asn1_decoder rsaprivkey_decoder = { 67 | .machine = rsaprivkey_machine, 68 | .machlen = sizeof(rsaprivkey_machine), 69 | .actions = rsaprivkey_action_table, 70 | }; 71 | -------------------------------------------------------------------------------- /asn/rsaprivkey-asn1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for rsaprivkey 5 | */ 6 | #include "asn1_decoder.h" 7 | 8 | extern const struct asn1_decoder rsaprivkey_decoder; 9 | 10 | extern int rsa_get_d(void *, size_t, unsigned char, const void *, size_t); 11 | extern int rsa_get_dp(void *, size_t, unsigned char, const void *, size_t); 12 | extern int rsa_get_dq(void *, size_t, unsigned char, const void *, size_t); 13 | extern int rsa_get_e(void *, size_t, unsigned char, const void *, size_t); 14 | extern int rsa_get_n(void *, size_t, unsigned char, const void *, size_t); 15 | extern int rsa_get_p(void *, size_t, unsigned char, const void *, size_t); 16 | extern int rsa_get_q(void *, size_t, unsigned char, const void *, size_t); 17 | extern int rsa_get_qinv(void *, size_t, unsigned char, const void *, size_t); 18 | 19 | -------------------------------------------------------------------------------- /asn/rsapubkey-asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for rsapubkey 5 | */ 6 | #include "asn1_ber_bytecode.h" 7 | #include "rsapubkey-asn1.h" 8 | 9 | enum rsapubkey_actions { 10 | ACT_rsa_get_e = 0, 11 | ACT_rsa_get_n = 1, 12 | NR__rsapubkey_actions = 2 13 | }; 14 | 15 | static const asn1_action_t rsapubkey_action_table[NR__rsapubkey_actions] = { 16 | [ 0] = rsa_get_e, 17 | [ 1] = rsa_get_n, 18 | }; 19 | 20 | static const unsigned char rsapubkey_machine[] = { 21 | // RsaPubKey 22 | [ 0] = ASN1_OP_MATCH, 23 | [ 1] = _tag(UNIV, CONS, SEQ), 24 | [ 2] = ASN1_OP_MATCH_ACT, // n 25 | [ 3] = _tag(UNIV, PRIM, INT), 26 | [ 4] = _action(ACT_rsa_get_n), 27 | [ 5] = ASN1_OP_MATCH_ACT, // e 28 | [ 6] = _tag(UNIV, PRIM, INT), 29 | [ 7] = _action(ACT_rsa_get_e), 30 | [ 8] = ASN1_OP_END_SEQ, 31 | [ 9] = ASN1_OP_COMPLETE, 32 | }; 33 | 34 | const struct asn1_decoder rsapubkey_decoder = { 35 | .machine = rsapubkey_machine, 36 | .machlen = sizeof(rsapubkey_machine), 37 | .actions = rsapubkey_action_table, 38 | }; 39 | -------------------------------------------------------------------------------- /asn/rsapubkey-asn1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for rsapubkey 5 | */ 6 | #include "asn1_decoder.h" 7 | 8 | extern const struct asn1_decoder rsapubkey_decoder; 9 | 10 | extern int rsa_get_e(void *, size_t, unsigned char, const void *, size_t); 11 | extern int rsa_get_n(void *, size_t, unsigned char, const void *, size_t); 12 | 13 | -------------------------------------------------------------------------------- /asn/x509-asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for x509 5 | */ 6 | #include "asn1_ber_bytecode.h" 7 | #include "x509-asn1.h" 8 | 9 | enum x509_actions { 10 | ACT_x509_extract_key_data = 0, 11 | ACT_x509_extract_name_segment = 1, 12 | ACT_x509_note_OID = 2, 13 | ACT_x509_note_issuer = 3, 14 | ACT_x509_note_not_after = 4, 15 | ACT_x509_note_not_before = 5, 16 | ACT_x509_note_pkey_algo = 6, 17 | ACT_x509_note_serial = 7, 18 | ACT_x509_note_signature = 8, 19 | ACT_x509_note_subject = 9, 20 | ACT_x509_note_tbs_certificate = 10, 21 | ACT_x509_process_extension = 11, 22 | NR__x509_actions = 12 23 | }; 24 | 25 | static const asn1_action_t x509_action_table[NR__x509_actions] = { 26 | [ 0] = x509_extract_key_data, 27 | [ 1] = x509_extract_name_segment, 28 | [ 2] = x509_note_OID, 29 | [ 3] = x509_note_issuer, 30 | [ 4] = x509_note_not_after, 31 | [ 5] = x509_note_not_before, 32 | [ 6] = x509_note_pkey_algo, 33 | [ 7] = x509_note_serial, 34 | [ 8] = x509_note_signature, 35 | [ 9] = x509_note_subject, 36 | [ 10] = x509_note_tbs_certificate, 37 | [ 11] = x509_process_extension, 38 | }; 39 | 40 | static const unsigned char x509_machine[] = { 41 | // Certificate 42 | [ 0] = ASN1_OP_MATCH, 43 | [ 1] = _tag(UNIV, CONS, SEQ), 44 | // TBSCertificate 45 | [ 2] = ASN1_OP_MATCH, 46 | [ 3] = _tag(UNIV, CONS, SEQ), 47 | [ 4] = ASN1_OP_MATCH_JUMP_OR_SKIP, // version 48 | [ 5] = _tagn(CONT, CONS, 0), 49 | [ 6] = _jump_target(70), 50 | // CertificateSerialNumber 51 | [ 7] = ASN1_OP_MATCH, 52 | [ 8] = _tag(UNIV, PRIM, INT), 53 | [ 9] = ASN1_OP_ACT, 54 | [ 10] = _action(ACT_x509_note_serial), 55 | // AlgorithmIdentifier 56 | [ 11] = ASN1_OP_MATCH_JUMP, 57 | [ 12] = _tag(UNIV, CONS, SEQ), 58 | [ 13] = _jump_target(74), // --> AlgorithmIdentifier 59 | [ 14] = ASN1_OP_ACT, 60 | [ 15] = _action(ACT_x509_note_pkey_algo), 61 | // Name 62 | [ 16] = ASN1_OP_MATCH_JUMP, 63 | [ 17] = _tag(UNIV, CONS, SEQ), 64 | [ 18] = _jump_target(80), // --> Name 65 | [ 19] = ASN1_OP_ACT, 66 | [ 20] = _action(ACT_x509_note_issuer), 67 | // Validity 68 | [ 21] = ASN1_OP_MATCH, 69 | [ 22] = _tag(UNIV, CONS, SEQ), 70 | // Time 71 | [ 23] = ASN1_OP_MATCH_OR_SKIP, // utcTime 72 | [ 24] = _tag(UNIV, PRIM, UNITIM), 73 | [ 25] = ASN1_OP_COND_MATCH_OR_SKIP, // generalTime 74 | [ 26] = _tag(UNIV, PRIM, GENTIM), 75 | [ 27] = ASN1_OP_COND_FAIL, 76 | [ 28] = ASN1_OP_ACT, 77 | [ 29] = _action(ACT_x509_note_not_before), 78 | // Time 79 | [ 30] = ASN1_OP_MATCH_OR_SKIP, // utcTime 80 | [ 31] = _tag(UNIV, PRIM, UNITIM), 81 | [ 32] = ASN1_OP_COND_MATCH_OR_SKIP, // generalTime 82 | [ 33] = _tag(UNIV, PRIM, GENTIM), 83 | [ 34] = ASN1_OP_COND_FAIL, 84 | [ 35] = ASN1_OP_ACT, 85 | [ 36] = _action(ACT_x509_note_not_after), 86 | [ 37] = ASN1_OP_END_SEQ, 87 | // Name 88 | [ 38] = ASN1_OP_MATCH_JUMP, 89 | [ 39] = _tag(UNIV, CONS, SEQ), 90 | [ 40] = _jump_target(80), // --> Name 91 | [ 41] = ASN1_OP_ACT, 92 | [ 42] = _action(ACT_x509_note_subject), 93 | // SubjectPublicKeyInfo 94 | [ 43] = ASN1_OP_MATCH, 95 | [ 44] = _tag(UNIV, CONS, SEQ), 96 | // AlgorithmIdentifier 97 | [ 45] = ASN1_OP_MATCH_JUMP, 98 | [ 46] = _tag(UNIV, CONS, SEQ), 99 | [ 47] = _jump_target(74), // --> AlgorithmIdentifier 100 | [ 48] = ASN1_OP_MATCH_ACT, // subjectPublicKey 101 | [ 49] = _tag(UNIV, PRIM, BTS), 102 | [ 50] = _action(ACT_x509_extract_key_data), 103 | [ 51] = ASN1_OP_END_SEQ, 104 | // UniqueIdentifier 105 | [ 52] = ASN1_OP_MATCH_OR_SKIP, // issuerUniqueID 106 | [ 53] = _tagn(CONT, PRIM, 1), 107 | // UniqueIdentifier 108 | [ 54] = ASN1_OP_MATCH_OR_SKIP, // subjectUniqueID 109 | [ 55] = _tagn(CONT, PRIM, 2), 110 | [ 56] = ASN1_OP_MATCH_JUMP_OR_SKIP, // extensions 111 | [ 57] = _tagn(CONT, CONS, 3), 112 | [ 58] = _jump_target(95), 113 | [ 59] = ASN1_OP_END_SEQ, 114 | [ 60] = ASN1_OP_ACT, 115 | [ 61] = _action(ACT_x509_note_tbs_certificate), 116 | // AlgorithmIdentifier 117 | [ 62] = ASN1_OP_MATCH_JUMP, 118 | [ 63] = _tag(UNIV, CONS, SEQ), 119 | [ 64] = _jump_target(74), // --> AlgorithmIdentifier 120 | [ 65] = ASN1_OP_MATCH_ACT, // signature 121 | [ 66] = _tag(UNIV, PRIM, BTS), 122 | [ 67] = _action(ACT_x509_note_signature), 123 | [ 68] = ASN1_OP_END_SEQ, 124 | [ 69] = ASN1_OP_COMPLETE, 125 | 126 | // Version 127 | [ 70] = ASN1_OP_MATCH, 128 | [ 71] = _tag(UNIV, PRIM, INT), 129 | [ 72] = ASN1_OP_END_SEQ, 130 | [ 73] = ASN1_OP_RETURN, 131 | 132 | [ 74] = ASN1_OP_MATCH_ACT, // algorithm 133 | [ 75] = _tag(UNIV, PRIM, OID), 134 | [ 76] = _action(ACT_x509_note_OID), 135 | [ 77] = ASN1_OP_MATCH_ANY_OR_SKIP, // parameters 136 | [ 78] = ASN1_OP_END_SEQ, 137 | [ 79] = ASN1_OP_RETURN, 138 | 139 | // RelativeDistinguishedName 140 | [ 80] = ASN1_OP_MATCH, 141 | [ 81] = _tag(UNIV, CONS, SET), 142 | // AttributeValueAssertion 143 | [ 82] = ASN1_OP_MATCH, 144 | [ 83] = _tag(UNIV, CONS, SEQ), 145 | [ 84] = ASN1_OP_MATCH_ACT, // attributeType 146 | [ 85] = _tag(UNIV, PRIM, OID), 147 | [ 86] = _action(ACT_x509_note_OID), 148 | [ 87] = ASN1_OP_MATCH_ANY_ACT, // attributeValue 149 | [ 88] = _action(ACT_x509_extract_name_segment), 150 | [ 89] = ASN1_OP_END_SEQ, 151 | [ 90] = ASN1_OP_END_SET_OF, 152 | [ 91] = _jump_target(82), 153 | [ 92] = ASN1_OP_END_SEQ_OF, 154 | [ 93] = _jump_target(80), 155 | [ 94] = ASN1_OP_RETURN, 156 | 157 | // Extensions 158 | [ 95] = ASN1_OP_MATCH, 159 | [ 96] = _tag(UNIV, CONS, SEQ), 160 | // Extension 161 | [ 97] = ASN1_OP_MATCH, 162 | [ 98] = _tag(UNIV, CONS, SEQ), 163 | [ 99] = ASN1_OP_MATCH_ACT, // extnid 164 | [ 100] = _tag(UNIV, PRIM, OID), 165 | [ 101] = _action(ACT_x509_note_OID), 166 | [ 102] = ASN1_OP_MATCH_OR_SKIP, // critical 167 | [ 103] = _tag(UNIV, PRIM, BOOL), 168 | [ 104] = ASN1_OP_MATCH_ACT, // extnValue 169 | [ 105] = _tag(UNIV, PRIM, OTS), 170 | [ 106] = _action(ACT_x509_process_extension), 171 | [ 107] = ASN1_OP_END_SEQ, 172 | [ 108] = ASN1_OP_END_SEQ_OF, 173 | [ 109] = _jump_target(97), 174 | [ 110] = ASN1_OP_END_SEQ, 175 | [ 111] = ASN1_OP_RETURN, 176 | }; 177 | 178 | const struct asn1_decoder x509_decoder = { 179 | .machine = x509_machine, 180 | .machlen = sizeof(x509_machine), 181 | .actions = x509_action_table, 182 | }; 183 | -------------------------------------------------------------------------------- /asn/x509-asn1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for x509 5 | */ 6 | #include "asn1_decoder.h" 7 | 8 | extern const struct asn1_decoder x509_decoder; 9 | 10 | extern int x509_extract_key_data(void *, size_t, unsigned char, const void *, size_t); 11 | extern int x509_extract_name_segment(void *, size_t, unsigned char, const void *, size_t); 12 | extern int x509_note_OID(void *, size_t, unsigned char, const void *, size_t); 13 | extern int x509_note_issuer(void *, size_t, unsigned char, const void *, size_t); 14 | extern int x509_note_not_after(void *, size_t, unsigned char, const void *, size_t); 15 | extern int x509_note_not_before(void *, size_t, unsigned char, const void *, size_t); 16 | extern int x509_note_pkey_algo(void *, size_t, unsigned char, const void *, size_t); 17 | extern int x509_note_serial(void *, size_t, unsigned char, const void *, size_t); 18 | extern int x509_note_signature(void *, size_t, unsigned char, const void *, size_t); 19 | extern int x509_note_subject(void *, size_t, unsigned char, const void *, size_t); 20 | extern int x509_note_tbs_certificate(void *, size_t, unsigned char, const void *, size_t); 21 | extern int x509_process_extension(void *, size_t, unsigned char, const void *, size_t); 22 | 23 | -------------------------------------------------------------------------------- /asn/x509_cert.h: -------------------------------------------------------------------------------- 1 | #ifndef __X509_CERT_H__ 2 | #define __X509_CERT_H__ 3 | 4 | #include "misc.h" 5 | 6 | struct x509_certificate { 7 | struct x509_certificate *next; 8 | struct x509_certificate *signer; /* Certificate that signed this one */ 9 | char *issuer; /* Name of certificate issuer */ 10 | char *subject; /* Name of certificate subject */ 11 | char *fingerprint; /* Key fingerprint as hex */ 12 | char *authority; /* Authority key fingerprint as hex */ 13 | time64_t valid_from; 14 | time64_t valid_to; 15 | const void *tbs; /* Signed data */ 16 | unsigned tbs_size; /* Size of signed data */ 17 | unsigned raw_sig_size; /* Size of sigature */ 18 | const void *raw_sig; /* Signature data */ 19 | const void *raw_serial; /* Raw serial number in ASN.1 */ 20 | unsigned raw_serial_size; 21 | unsigned raw_issuer_size; 22 | const void *raw_issuer; /* Raw issuer name in ASN.1 */ 23 | const void *raw_subject; /* Raw subject name in ASN.1 */ 24 | unsigned raw_subject_size; 25 | unsigned index; 26 | }; 27 | 28 | void x509_free_certificate(struct x509_certificate *cert); 29 | struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); 30 | 31 | #endif //__X509_CERT_H__ 32 | -------------------------------------------------------------------------------- /asn/x509_cert_parser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "x509-asn1.h" 10 | #include "x509_rsakey-asn1.h" 11 | #include "x509_cert.h" 12 | #include "oid_registry.h" 13 | #include "misc.h" 14 | 15 | struct x509_parse_context { 16 | struct x509_certificate *cert; /* Certificate being constructed */ 17 | unsigned long data; /* Start of data */ 18 | const void *cert_start; /* Start of cert content */ 19 | const void *key; /* Key data */ 20 | size_t key_size; /* Size of key data */ 21 | enum OID last_oid; /* Last OID encountered */ 22 | enum OID algo_oid; /* Algorithm OID */ 23 | unsigned char nr_mpi; /* Number of MPIs stored */ 24 | u8 o_size; /* Size of organizationName (O) */ 25 | u8 cn_size; /* Size of commonName (CN) */ 26 | u8 email_size; /* Size of emailAddress */ 27 | u16 o_offset; /* Offset of organizationName (O) */ 28 | u16 cn_offset; /* Offset of commonName (CN) */ 29 | u16 email_offset; /* Offset of emailAddress */ 30 | }; 31 | 32 | /* 33 | * Free an X.509 certificate 34 | */ 35 | void x509_free_certificate(struct x509_certificate *cert) 36 | { 37 | if (cert) { 38 | free(cert->issuer); 39 | free(cert->subject); 40 | free(cert->fingerprint); 41 | free(cert->authority); 42 | free(cert); 43 | } 44 | } 45 | 46 | /* 47 | * Parse an X.509 certificate 48 | */ 49 | struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) 50 | { 51 | struct x509_certificate *cert; 52 | struct x509_parse_context *ctx; 53 | long ret; 54 | 55 | ret = -ENOMEM; 56 | cert = calloc(1, sizeof(struct x509_certificate)); 57 | if (!cert) 58 | goto error_no_cert; 59 | ctx = calloc(1, sizeof(struct x509_parse_context)); 60 | if (!ctx) 61 | goto error_no_ctx; 62 | 63 | ctx->cert = cert; 64 | ctx->data = (unsigned long)data; 65 | 66 | /* Attempt to decode the certificate */ 67 | ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); 68 | if (ret < 0) 69 | goto error_decode; 70 | 71 | /* Decode the public key */ 72 | ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, 73 | ctx->key, ctx->key_size); 74 | if (ret < 0) 75 | goto error_decode; 76 | 77 | free(ctx); 78 | return cert; 79 | 80 | error_decode: 81 | free(ctx); 82 | error_no_ctx: 83 | x509_free_certificate(cert); 84 | error_no_cert: 85 | return NULL; 86 | } 87 | 88 | /* 89 | * Fabricate and save the issuer and subject names 90 | */ 91 | static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, unsigned char tag, char **_name, size_t vlen) 92 | { 93 | const void *name, *data = (const void *)ctx->data; 94 | size_t namesize; 95 | char *buffer; 96 | 97 | if (*_name) 98 | return -EINVAL; 99 | 100 | /* Empty name string if no material */ 101 | if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { 102 | buffer = malloc(1); 103 | if (!buffer) 104 | return -ENOMEM; 105 | buffer[0] = 0; 106 | goto done; 107 | } 108 | 109 | if (ctx->cn_size && ctx->o_size) { 110 | /* Consider combining O and CN, but use only the CN if it is 111 | * prefixed by the O, or a significant portion thereof. 112 | */ 113 | namesize = ctx->cn_size; 114 | name = data + ctx->cn_offset; 115 | if (ctx->cn_size >= ctx->o_size && 116 | memcmp(data + ctx->cn_offset, data + ctx->o_offset, 117 | ctx->o_size) == 0) 118 | goto single_component; 119 | if (ctx->cn_size >= 7 && 120 | ctx->o_size >= 7 && 121 | memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) 122 | goto single_component; 123 | 124 | buffer = malloc(ctx->o_size + 2 + ctx->cn_size + 1); 125 | if (!buffer) 126 | return -ENOMEM; 127 | 128 | memcpy(buffer, 129 | data + ctx->o_offset, ctx->o_size); 130 | buffer[ctx->o_size + 0] = ':'; 131 | buffer[ctx->o_size + 1] = ' '; 132 | memcpy(buffer + ctx->o_size + 2, 133 | data + ctx->cn_offset, ctx->cn_size); 134 | buffer[ctx->o_size + 2 + ctx->cn_size] = 0; 135 | goto done; 136 | 137 | } else if (ctx->cn_size) { 138 | namesize = ctx->cn_size; 139 | name = data + ctx->cn_offset; 140 | } else if (ctx->o_size) { 141 | namesize = ctx->o_size; 142 | name = data + ctx->o_offset; 143 | } else { 144 | namesize = ctx->email_size; 145 | name = data + ctx->email_offset; 146 | } 147 | 148 | single_component: 149 | buffer = malloc(namesize + 1); 150 | if (!buffer) 151 | return -ENOMEM; 152 | memcpy(buffer, name, namesize); 153 | buffer[namesize] = 0; 154 | 155 | done: 156 | *_name = buffer; 157 | ctx->cn_size = 0; 158 | ctx->o_size = 0; 159 | ctx->email_size = 0; 160 | return 0; 161 | } 162 | 163 | /** 164 | * x509_decode_time - Decode an X.509 time ASN.1 object 165 | * @_t: The time to fill in 166 | * @hdrlen: The length of the object header 167 | * @tag: The object tag 168 | * @value: The object value 169 | * @vlen: The size of the object value 170 | * 171 | * Decode an ASN.1 universal time or generalised time field into a struct the 172 | * kernel can handle and check it for validity. The time is decoded thus: 173 | * 174 | * [RFC5280 §4.1.2.5] 175 | * CAs conforming to this profile MUST always encode certificate validity 176 | * dates through the year 2049 as UTCTime; certificate validity dates in 177 | * 2050 or later MUST be encoded as GeneralizedTime. Conforming 178 | * applications MUST be able to process validity dates that are encoded in 179 | * either UTCTime or GeneralizedTime. 180 | */ 181 | int x509_decode_time(time64_t *_t, size_t hdrlen, 182 | unsigned char tag, 183 | const unsigned char *value, size_t vlen) 184 | { 185 | static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30, 186 | 31, 31, 30, 31, 30, 31 }; 187 | const unsigned char *p = value; 188 | unsigned year, mon, day, hour, min, sec, mon_len; 189 | 190 | #define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; }) 191 | #define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) 192 | 193 | if (tag == ASN1_UNITIM) { 194 | /* UTCTime: YYMMDDHHMMSSZ */ 195 | if (vlen != 13) 196 | goto unsupported_time; 197 | year = DD2bin(p); 198 | if (year >= 50) 199 | year += 1900; 200 | else 201 | year += 2000; 202 | } else if (tag == ASN1_GENTIM) { 203 | /* GenTime: YYYYMMDDHHMMSSZ */ 204 | if (vlen != 15) 205 | goto unsupported_time; 206 | year = DD2bin(p) * 100 + DD2bin(p); 207 | if (year >= 1950 && year <= 2049) 208 | goto invalid_time; 209 | } else { 210 | goto unsupported_time; 211 | } 212 | 213 | mon = DD2bin(p); 214 | day = DD2bin(p); 215 | hour = DD2bin(p); 216 | min = DD2bin(p); 217 | sec = DD2bin(p); 218 | 219 | if (*p != 'Z') 220 | goto unsupported_time; 221 | 222 | if (year < 1970 || 223 | mon < 1 || mon > 12) 224 | goto invalid_time; 225 | 226 | mon_len = month_lengths[mon - 1]; 227 | if (mon == 2) { 228 | if (year % 4 == 0) { 229 | mon_len = 29; 230 | if (year % 100 == 0) { 231 | mon_len = 28; 232 | if (year % 400 == 0) 233 | mon_len = 29; 234 | } 235 | } 236 | } 237 | 238 | if (day < 1 || day > mon_len || 239 | hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */ 240 | min > 59 || 241 | sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ 242 | goto invalid_time; 243 | 244 | struct tm t = { 245 | .tm_year = year, 246 | .tm_mon = mon, 247 | .tm_mday = day, 248 | .tm_hour = hour, 249 | .tm_min = min, 250 | .tm_sec = sec, 251 | }; 252 | *_t = mktime(&t); 253 | return 0; 254 | 255 | unsupported_time: 256 | pr_debug("Got unsupported time [tag %02x]: '%*phN'\n", 257 | tag, (int)vlen, value); 258 | return -EBADMSG; 259 | invalid_time: 260 | pr_debug("Got invalid time [tag %02x]: '%*phN'\n", 261 | tag, (int)vlen, value); 262 | return -EBADMSG; 263 | } 264 | 265 | /* 266 | * Extract the data for the public key algorithm 267 | */ 268 | int x509_extract_key_data(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 269 | { 270 | struct x509_parse_context *ctx = context; 271 | 272 | pr_debug("x509_extract_key_data %p %lu\n", value, vlen); 273 | if (ctx->last_oid != OID_rsaEncryption) 274 | return -ENOPKG; 275 | 276 | /* Discard the BIT STRING metadata */ 277 | ctx->key = value + 1; 278 | ctx->key_size = vlen - 1; 279 | return 0; 280 | } 281 | 282 | /* 283 | * Note some of the name segments from which we'll fabricate a name. 284 | */ 285 | int x509_extract_name_segment(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 286 | { 287 | struct x509_parse_context *ctx = context; 288 | 289 | pr_debug("x509_extract_name_segment %p %lu\n", value, vlen); 290 | switch (ctx->last_oid) { 291 | case OID_commonName: 292 | ctx->cn_size = vlen; 293 | ctx->cn_offset = (unsigned long)value - ctx->data; 294 | break; 295 | case OID_organizationName: 296 | ctx->o_size = vlen; 297 | ctx->o_offset = (unsigned long)value - ctx->data; 298 | break; 299 | case OID_email_address: 300 | ctx->email_size = vlen; 301 | ctx->email_offset = (unsigned long)value - ctx->data; 302 | break; 303 | default: 304 | break; 305 | } 306 | 307 | return 0; 308 | } 309 | 310 | /* 311 | * Note an OID when we find one for later processing when we know how 312 | * to interpret it. 313 | */ 314 | int x509_note_OID(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 315 | { 316 | struct x509_parse_context *ctx = context; 317 | 318 | pr_debug("x509_note_OID %p %lu\n", value, vlen); 319 | ctx->last_oid = look_up_OID(value, vlen); 320 | if (ctx->last_oid == OID__NR) { 321 | char buffer[50]; 322 | sprint_oid(value, vlen, buffer, sizeof(buffer)); 323 | pr_debug("Unknown OID: [%lu] %s\n", 324 | (unsigned long)value - ctx->data, buffer); 325 | } 326 | return 0; 327 | } 328 | 329 | int x509_note_issuer(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 330 | { 331 | struct x509_parse_context *ctx = context; 332 | int ret; 333 | char * name; 334 | pr_debug("x509_note_issuer %p %lu\n", value, vlen); 335 | ctx->cert->raw_issuer = value; 336 | ctx->cert->raw_issuer_size = vlen; 337 | return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); 338 | } 339 | 340 | int x509_note_not_before(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 341 | { 342 | struct x509_parse_context *ctx = context; 343 | pr_debug("x509_note_not_before %p %lu\n", value, vlen); 344 | return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); 345 | } 346 | 347 | int x509_note_not_after(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 348 | { 349 | struct x509_parse_context *ctx = context; 350 | pr_debug("x509_note_not_after %p %lu\n", value, vlen); 351 | return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); 352 | } 353 | 354 | int x509_note_pkey_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 355 | { 356 | struct x509_parse_context *ctx = context; 357 | 358 | pr_debug("PubKey Algo: %u\n", ctx->last_oid); 359 | 360 | pr_debug("x509_note_pkey_algo %p %lu\n", value, vlen); 361 | switch (ctx->last_oid) { 362 | case OID_md2WithRSAEncryption: 363 | case OID_md3WithRSAEncryption: 364 | default: 365 | return -ENOPKG; /* Unsupported combination */ 366 | 367 | case OID_md4WithRSAEncryption: 368 | puts("pkey_hash_algo HASH_ALGO_MD5 pkey_algo PKEY_ALGO_RSA\n"); 369 | break; 370 | 371 | case OID_sha1WithRSAEncryption: 372 | puts("pkey_hash_algo HASH_ALGO_SHA1 pkey_algo PKEY_ALGO_RSA\n"); 373 | break; 374 | 375 | case OID_sha256WithRSAEncryption: 376 | puts("pkey_hash_algo HASH_ALGO_SHA256 pkey_algo PKEY_ALGO_RSA\n"); 377 | break; 378 | 379 | case OID_sha384WithRSAEncryption: 380 | puts("pkey_hash_algo HASH_ALGO_SHA384 pkey_algo PKEY_ALGO_RSA\n"); 381 | break; 382 | 383 | case OID_sha512WithRSAEncryption: 384 | puts("pkey_hash_algo HASH_ALGO_SHA512 pkey_algo PKEY_ALGO_RSA\n"); 385 | break; 386 | 387 | case OID_sha224WithRSAEncryption: 388 | puts("pkey_hash_algo HASH_ALGO_SHA224 pkey_algo PKEY_ALGO_RSA\n"); 389 | break; 390 | } 391 | 392 | ctx->algo_oid = ctx->last_oid; 393 | return 0; 394 | } 395 | 396 | /* 397 | * Note the certificate serial number 398 | */ 399 | int x509_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 400 | { 401 | struct x509_parse_context *ctx = context; 402 | pr_debug("x509_note_serial %p %lu\n", value, vlen); 403 | ctx->cert->raw_serial = value; 404 | ctx->cert->raw_serial_size = vlen; 405 | return 0; 406 | } 407 | 408 | int x509_note_signature(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 409 | { 410 | struct x509_parse_context *ctx = context; 411 | 412 | pr_debug("x509_note_signature %p %lu\n", value, vlen); 413 | 414 | pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); 415 | 416 | if (ctx->last_oid != ctx->algo_oid) { 417 | pr_warn("WARNING: Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", 418 | ctx->algo_oid, ctx->last_oid); 419 | return -EINVAL; 420 | } 421 | 422 | ctx->cert->raw_sig = value; 423 | ctx->cert->raw_sig_size = vlen; 424 | return 0; 425 | } 426 | 427 | int x509_note_subject(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 428 | { 429 | struct x509_parse_context *ctx = context; 430 | pr_debug("x509_note_subject %p %lu\n", value, vlen); 431 | ctx->cert->raw_subject = value; 432 | ctx->cert->raw_subject_size = vlen; 433 | return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); 434 | } 435 | 436 | /* 437 | * Save the position of the TBS data so that we can check the signature over it 438 | * later. 439 | */ 440 | int x509_note_tbs_certificate(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 441 | { 442 | struct x509_parse_context *ctx = context; 443 | 444 | pr_debug("x509_note_tbs_certificate %p %lu\n", value, vlen); 445 | 446 | pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", 447 | hdrlen, tag, (unsigned long)value - ctx->data, vlen); 448 | 449 | ctx->cert->tbs = value - hdrlen; 450 | ctx->cert->tbs_size = vlen + hdrlen; 451 | return 0; 452 | } 453 | 454 | /* 455 | * Extract a RSA public key value 456 | */ 457 | int rsa_extract_mpi(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 458 | { 459 | //We don't actually care about getting the key here 460 | //and trying to compile in the MPI library is too much work 461 | #if 0 462 | struct x509_parse_context *ctx = context; 463 | MPI mpi; 464 | 465 | if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { 466 | pr_err("Too many public key MPIs in certificate\n"); 467 | return -EBADMSG; 468 | } 469 | 470 | mpi = mpi_read_raw_data(value, vlen); 471 | if (!mpi) 472 | return -ENOMEM; 473 | 474 | ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; 475 | #endif 476 | return 0; 477 | } 478 | 479 | /* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ 480 | #define SEQ_TAG_KEYID (ASN1_CONT << 6) 481 | 482 | /* 483 | * Process certificate extensions that are used to qualify the certificate. 484 | */ 485 | int x509_process_extension(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) 486 | { 487 | struct x509_parse_context *ctx = context; 488 | const unsigned char *v = value; 489 | char *f; 490 | int i; 491 | 492 | pr_debug("x509_process_extension %p %lu\n", value, vlen); 493 | pr_debug("Extension: %u\n", ctx->last_oid); 494 | 495 | if (ctx->last_oid == OID_subjectKeyIdentifier) { 496 | /* Get hold of the key fingerprint */ 497 | if (vlen < 3) 498 | return -EBADMSG; 499 | if (v[0] != ASN1_OTS || v[1] != vlen - 2) 500 | return -EBADMSG; 501 | v += 2; 502 | vlen -= 2; 503 | 504 | f = malloc(vlen * 2 + 1); 505 | if (!f) 506 | return -ENOMEM; 507 | for (i = 0; i < vlen; i++) 508 | sprintf(f + i * 2, "%02x", v[i]); 509 | pr_debug("fingerprint %s\n", f); 510 | ctx->cert->fingerprint = f; 511 | return 0; 512 | } 513 | 514 | if (ctx->last_oid == OID_authorityKeyIdentifier) { 515 | size_t key_len; 516 | 517 | /* Get hold of the CA key fingerprint */ 518 | if (vlen < 5) 519 | return -EBADMSG; 520 | 521 | /* Authority Key Identifier must be a Constructed SEQUENCE */ 522 | if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5))) 523 | return -EBADMSG; 524 | 525 | /* Authority Key Identifier is not indefinite length */ 526 | if (unlikely(vlen == ASN1_INDEFINITE_LENGTH)) 527 | return -EBADMSG; 528 | 529 | if (vlen < ASN1_INDEFINITE_LENGTH) { 530 | /* Short Form length */ 531 | if (v[1] != vlen - 2 || 532 | v[2] != SEQ_TAG_KEYID || 533 | v[3] > vlen - 4) 534 | return -EBADMSG; 535 | 536 | key_len = v[3]; 537 | v += 4; 538 | } else { 539 | /* Long Form length */ 540 | size_t seq_len = 0; 541 | size_t sub = v[1] - ASN1_INDEFINITE_LENGTH; 542 | 543 | if (sub > 2) 544 | return -EBADMSG; 545 | 546 | /* calculate the length from subsequent octets */ 547 | v += 2; 548 | for (i = 0; i < sub; i++) { 549 | seq_len <<= 8; 550 | seq_len |= v[i]; 551 | } 552 | 553 | if (seq_len != vlen - 2 - sub || 554 | v[sub] != SEQ_TAG_KEYID || 555 | v[sub + 1] > vlen - 4 - sub) 556 | return -EBADMSG; 557 | 558 | key_len = v[sub + 1]; 559 | v += (sub + 2); 560 | } 561 | 562 | f = malloc(key_len * 2 + 1); 563 | if (!f) 564 | return -ENOMEM; 565 | for (i = 0; i < key_len; i++) 566 | sprintf(f + i * 2, "%02x", v[i]); 567 | pr_debug("authority %s\n", f); 568 | ctx->cert->authority = f; 569 | return 0; 570 | } 571 | 572 | return 0; 573 | } 574 | 575 | -------------------------------------------------------------------------------- /asn/x509_inputs.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grimm-co/linuxklee/14e85ec2b8cbe89064f6e268aa3045f64ad1fce8/asn/x509_inputs.tar.xz -------------------------------------------------------------------------------- /asn/x509_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #ifdef KLEE 9 | #include 10 | #endif 11 | 12 | #include "x509_cert.h" 13 | #include "misc.h" 14 | 15 | #ifdef KLEE 16 | #define FUZZ_BUFFER_SIZE 1024 17 | #elif defined(KLEE_DEBUG) 18 | #define FUZZ_BUFFER_SIZE 1024 19 | #else 20 | #define FUZZ_BUFFER_SIZE (2*1024*1024) 21 | #endif 22 | 23 | int main(int argc, char **argv) 24 | { 25 | struct x509_certificate * cert; 26 | char * fuzz_filename; 27 | int fuzz_length; 28 | char * fuzz_buffer; 29 | 30 | fuzz_buffer = malloc(FUZZ_BUFFER_SIZE); 31 | if(!fuzz_buffer) { 32 | printf("Failed to allocate fuzz buffer\n"); 33 | return 1; 34 | } 35 | pr_debug("fuzz_buffer %p\n", fuzz_buffer); 36 | 37 | #ifndef KLEE 38 | if(argc < 2) { 39 | printf("Usage: x509 filename\n"); 40 | return 1; 41 | } 42 | fuzz_filename = argv[1]; 43 | #endif 44 | 45 | #ifdef __AFL_HAVE_MANUAL_CONTROL 46 | __AFL_INIT(); 47 | #endif 48 | 49 | #ifdef __AFL_LOOP 50 | while (__AFL_LOOP(1000)) { 51 | #endif 52 | 53 | memset(fuzz_buffer, 0, FUZZ_BUFFER_SIZE); 54 | 55 | #ifdef KLEE 56 | unsigned short size; 57 | klee_make_symbolic(&size, sizeof(short), "size"); 58 | size &= 0x3ff; 59 | 60 | klee_assume(size < FUZZ_BUFFER_SIZE); 61 | fuzz_length = size; 62 | if(fuzz_length == 0) 63 | return 1; 64 | 65 | klee_make_symbolic(fuzz_buffer, FUZZ_BUFFER_SIZE, "buffer"); 66 | 67 | #else 68 | 69 | fuzz_length = read_file(fuzz_filename, fuzz_buffer, FUZZ_BUFFER_SIZE); 70 | if(fuzz_length < 0) 71 | #ifdef __AFL_LOOP 72 | continue; 73 | #else 74 | return 1; 75 | #endif 76 | 77 | #endif 78 | 79 | cert = x509_cert_parse(fuzz_buffer, fuzz_length); 80 | x509_free_certificate(cert); 81 | 82 | #ifdef __AFL_LOOP 83 | } 84 | #endif 85 | 86 | free(fuzz_buffer); 87 | 88 | return 0; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /asn/x509_rsakey-asn1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for x509_rsakey 5 | */ 6 | #include "asn1_ber_bytecode.h" 7 | #include "x509_rsakey-asn1.h" 8 | 9 | enum x509_rsakey_actions { 10 | ACT_rsa_extract_mpi = 0, 11 | NR__x509_rsakey_actions = 1 12 | }; 13 | 14 | static const asn1_action_t x509_rsakey_action_table[NR__x509_rsakey_actions] = { 15 | [ 0] = rsa_extract_mpi, 16 | }; 17 | 18 | static const unsigned char x509_rsakey_machine[] = { 19 | // RSAPublicKey 20 | [ 0] = ASN1_OP_MATCH, 21 | [ 1] = _tag(UNIV, CONS, SEQ), 22 | [ 2] = ASN1_OP_MATCH_ACT, // modulus 23 | [ 3] = _tag(UNIV, PRIM, INT), 24 | [ 4] = _action(ACT_rsa_extract_mpi), 25 | [ 5] = ASN1_OP_MATCH_ACT, // publicExponent 26 | [ 6] = _tag(UNIV, PRIM, INT), 27 | [ 7] = _action(ACT_rsa_extract_mpi), 28 | [ 8] = ASN1_OP_END_SEQ, 29 | [ 9] = ASN1_OP_COMPLETE, 30 | }; 31 | 32 | const struct asn1_decoder x509_rsakey_decoder = { 33 | .machine = x509_rsakey_machine, 34 | .machlen = sizeof(x509_rsakey_machine), 35 | .actions = x509_rsakey_action_table, 36 | }; 37 | -------------------------------------------------------------------------------- /asn/x509_rsakey-asn1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated by asn1_compiler. Do not edit 3 | * 4 | * ASN.1 parser for x509_rsakey 5 | */ 6 | #include "asn1_decoder.h" 7 | 8 | extern const struct asn1_decoder x509_rsakey_decoder; 9 | 10 | extern int rsa_extract_mpi(void *, size_t, unsigned char, const void *, size_t); 11 | 12 | -------------------------------------------------------------------------------- /asn/x509_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define BUFFER_SIZE (1024*1024) 12 | 13 | int read_file(char * filename, char *buffer, long length) 14 | { 15 | FILE *fp; 16 | long fsize, total = 0, num_read; 17 | 18 | fp = fopen(filename, "rb"); 19 | if (!fp) 20 | return -1; 21 | 22 | //Get the size 23 | fseek(fp, 0, SEEK_END); 24 | fsize = ftell(fp); 25 | fseek(fp, 0, SEEK_SET); 26 | 27 | if(fsize > length) 28 | fsize = length; 29 | 30 | while (total < fsize) 31 | { 32 | num_read = fread(buffer + total, 1, fsize, fp); 33 | total += num_read; 34 | } 35 | 36 | fclose(fp); 37 | 38 | return fsize; 39 | } 40 | 41 | int main(int argc, char ** argv) 42 | { 43 | unsigned char buffer[BUFFER_SIZE]; 44 | int length; 45 | 46 | length = read_file(argv[1], buffer, BUFFER_SIZE); 47 | if(length < 0) { 48 | printf("Couldn't read %s\n", argv[1]); 49 | return 1; 50 | } 51 | 52 | syscall(__NR_add_key, "asymmetric", NULL, buffer, length, KEY_SPEC_SESSION_KEYRING); 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /bc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: bc bc_debug 3 | 4 | SRC=main.c 5 | 6 | bc: 7 | $(CC) $(CFLAGS) $(SRC) -o bc 8 | 9 | bc_debug: 10 | $(CC) -DDEBUG -g $(SRC) -o bc_debug 11 | 12 | bc_klee: 13 | clang -I klee_src/include/ -DKLEE -emit-llvm -g -c -O0 -Xclang -disable-O0-optnone main.c -o bc.bc 14 | 15 | clean: 16 | rm -f *.o bc bc_debug bc.bc 17 | 18 | .PHONY: bc bc_debug bc_klee 19 | -------------------------------------------------------------------------------- /bc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #ifdef KLEE 9 | #include 10 | #endif 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define bool int 18 | #define false 0 19 | #define true 1 20 | 21 | #define u16 uint16_t 22 | #define SOCK_BINDPORT_LOCK 8 23 | 24 | struct inet_diag_entry { 25 | const __be32 *saddr; 26 | const __be32 *daddr; 27 | u16 sport; 28 | u16 dport; 29 | u16 family; 30 | u16 userlocks; 31 | }; 32 | 33 | #ifndef DEBUG 34 | #define log(msg, ...) 35 | #else 36 | 37 | #define log(msg, ...) printf(msg, ##__VA_ARGS__) 38 | 39 | const char * op_name(unsigned char code) { 40 | switch (code) { 41 | case INET_DIAG_BC_S_COND: 42 | return "INET_DIAG_BC_S_COND"; 43 | case INET_DIAG_BC_D_COND: 44 | return "INET_DIAG_BC_D_COND"; 45 | case INET_DIAG_BC_S_GE: 46 | return "INET_DIAG_BC_S_GE"; 47 | case INET_DIAG_BC_S_LE: 48 | return "INET_DIAG_BC_S_LE"; 49 | case INET_DIAG_BC_D_GE: 50 | return "INET_DIAG_BC_D_GE"; 51 | case INET_DIAG_BC_D_LE: 52 | return "INET_DIAG_BC_D_LE"; 53 | case INET_DIAG_BC_AUTO: 54 | return "INET_DIAG_BC_AUTO"; 55 | case INET_DIAG_BC_JMP: 56 | return "INET_DIAG_BC_JMP"; 57 | case INET_DIAG_BC_NOP: 58 | return "INET_DIAG_BC_NOP"; 59 | } 60 | return "Unknown"; 61 | } 62 | #endif 63 | 64 | 65 | static int bitstring_match(const __be32 *a1, const __be32 *a2, int bits) 66 | { 67 | int words = bits >> 5; 68 | 69 | bits &= 0x1f; 70 | 71 | if (words) { 72 | if (memcmp(a1, a2, words << 2)) 73 | return 0; 74 | } 75 | if (bits) { 76 | __be32 w1, w2; 77 | __be32 mask; 78 | 79 | w1 = a1[words]; 80 | w2 = a2[words]; 81 | 82 | mask = htonl((0xffffffff) << (32 - bits)); 83 | 84 | if ((w1 ^ w2) & mask) 85 | return 0; 86 | } 87 | 88 | return 1; 89 | } 90 | 91 | static int inet_diag_bc_run(const void * bc, int len, 92 | const struct inet_diag_entry *entry) 93 | { 94 | #ifdef DEBUG 95 | const void * orig_bc = bc; 96 | #endif 97 | while (len > 0) { 98 | int yes = 1; 99 | const struct inet_diag_bc_op *op = bc; 100 | 101 | switch (op->code) { 102 | case INET_DIAG_BC_NOP: 103 | break; 104 | case INET_DIAG_BC_JMP: 105 | yes = 0; 106 | break; 107 | case INET_DIAG_BC_S_GE: 108 | yes = entry->sport >= op[1].no; 109 | break; 110 | case INET_DIAG_BC_S_LE: 111 | yes = entry->sport <= op[1].no; 112 | break; 113 | case INET_DIAG_BC_D_GE: 114 | yes = entry->dport >= op[1].no; 115 | break; 116 | case INET_DIAG_BC_D_LE: 117 | yes = entry->dport <= op[1].no; 118 | break; 119 | case INET_DIAG_BC_AUTO: 120 | yes = !(entry->userlocks & SOCK_BINDPORT_LOCK); 121 | break; 122 | case INET_DIAG_BC_S_COND: 123 | case INET_DIAG_BC_D_COND: { 124 | const struct inet_diag_hostcond *cond; 125 | const __be32 *addr; 126 | 127 | cond = (const struct inet_diag_hostcond *)(op + 1); 128 | if (cond->port != -1 && 129 | cond->port != (op->code == INET_DIAG_BC_S_COND ? 130 | entry->sport : entry->dport)) { 131 | yes = 0; 132 | break; 133 | } 134 | 135 | if (op->code == INET_DIAG_BC_S_COND) 136 | addr = entry->saddr; 137 | else 138 | addr = entry->daddr; 139 | 140 | if (cond->family != AF_UNSPEC && 141 | cond->family != entry->family) { 142 | if (entry->family == AF_INET6 && 143 | cond->family == AF_INET) { 144 | if (addr[0] == 0 && addr[1] == 0 && 145 | addr[2] == htonl(0xffff) && 146 | bitstring_match(addr + 3, 147 | cond->addr, 148 | cond->prefix_len)) 149 | break; 150 | } 151 | yes = 0; 152 | break; 153 | } 154 | 155 | if (cond->prefix_len == 0) 156 | break; 157 | if (bitstring_match(addr, cond->addr, 158 | cond->prefix_len)) 159 | break; 160 | yes = 0; 161 | break; 162 | } 163 | } 164 | 165 | log("pos %04ld len %04d: %15s (%d) - yes %5d no %5d - %s\n", bc - orig_bc, len, op_name(op->code), op->code, op->yes, op->no, yes ? "true" : "false"); 166 | 167 | if (yes) { 168 | len -= op->yes; 169 | bc += op->yes; 170 | } else { 171 | len -= op->no; 172 | bc += op->no; 173 | } 174 | } 175 | return len == 0; 176 | } 177 | 178 | static int valid_cc(const void *bc, int len, int cc) 179 | { 180 | while (len >= 0) { 181 | const struct inet_diag_bc_op *op = bc; 182 | 183 | log("cc %d len %d - %s (%d) - yes %d no %d\n", cc, len, op_name(op->code), op->code, op->yes, op->no); 184 | 185 | if (cc > len) { 186 | log("valid_cc failed - cc greater than len\n"); 187 | return 0; 188 | } 189 | if (cc == len) { 190 | log("valid_cc passed\n"); 191 | return 1; 192 | } 193 | if (op->yes < 4 || op->yes & 3) { 194 | log("valid_cc failed - yes not 4-aligned\n"); 195 | return 0; 196 | } 197 | len -= op->yes; 198 | bc += op->yes; 199 | } 200 | log("valid_cc failed - len ran out\n"); 201 | return 0; 202 | } 203 | 204 | /* Validate an inet_diag_hostcond. */ 205 | static bool valid_hostcond(const struct inet_diag_bc_op *op, int len, 206 | int *min_len) 207 | { 208 | struct inet_diag_hostcond *cond; 209 | int addr_len; 210 | 211 | /* Check hostcond space. */ 212 | *min_len += sizeof(struct inet_diag_hostcond); 213 | if (len < *min_len) 214 | return false; 215 | cond = (struct inet_diag_hostcond *)(op + 1); 216 | 217 | /* Check address family and address length. */ 218 | switch (cond->family) { 219 | case AF_UNSPEC: 220 | addr_len = 0; 221 | break; 222 | case AF_INET: 223 | addr_len = sizeof(struct in_addr); 224 | break; 225 | case AF_INET6: 226 | addr_len = sizeof(struct in6_addr); 227 | break; 228 | default: 229 | return false; 230 | } 231 | *min_len += addr_len; 232 | if (len < *min_len) 233 | return false; 234 | 235 | /* Check prefix length (in bits) vs address length (in bytes). */ 236 | if (cond->prefix_len > 8 * addr_len) 237 | return false; 238 | 239 | return true; 240 | } 241 | 242 | /* Validate a port comparison operator. */ 243 | static bool valid_port_comparison(const struct inet_diag_bc_op *op, 244 | int len, int *min_len) 245 | { 246 | /* Port comparisons put the port in a follow-on inet_diag_bc_op. */ 247 | *min_len += sizeof(struct inet_diag_bc_op); 248 | if (len < *min_len) 249 | return false; 250 | return true; 251 | } 252 | 253 | static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) 254 | { 255 | const void *bc = bytecode; 256 | int len = bytecode_len; 257 | 258 | while (len > 0) { 259 | int min_len = sizeof(struct inet_diag_bc_op); 260 | const struct inet_diag_bc_op *op = bc; 261 | 262 | log("%s (%d) - yes %d no %d\n", op_name(op->code), op->code, op->yes, op->no); 263 | 264 | switch (op->code) { 265 | case INET_DIAG_BC_S_COND: 266 | case INET_DIAG_BC_D_COND: 267 | if (!valid_hostcond(bc, len, &min_len)) 268 | return -EINVAL; 269 | break; 270 | case INET_DIAG_BC_S_GE: 271 | case INET_DIAG_BC_S_LE: 272 | case INET_DIAG_BC_D_GE: 273 | case INET_DIAG_BC_D_LE: 274 | if (!valid_port_comparison(bc, len, &min_len)) 275 | return -EINVAL; 276 | break; 277 | case INET_DIAG_BC_AUTO: 278 | case INET_DIAG_BC_JMP: 279 | case INET_DIAG_BC_NOP: 280 | break; 281 | default: 282 | return -EINVAL; 283 | } 284 | 285 | if (op->code != INET_DIAG_BC_NOP) { 286 | if (op->no < min_len || op->no > len + 4 || op->no & 3) 287 | return -EINVAL; 288 | if (op->no < len && 289 | !valid_cc(bytecode, bytecode_len, len - op->no)) 290 | return -EINVAL; 291 | } 292 | 293 | if (op->yes < min_len || op->yes > len + 4 || op->yes & 3) 294 | return -EINVAL; 295 | bc += op->yes; 296 | len -= op->yes; 297 | } 298 | return len == 0 ? 0 : -EINVAL; 299 | } 300 | 301 | int read_file(char * filename, char *buffer, long length) 302 | { 303 | FILE *fp; 304 | long fsize, total = 0, num_read; 305 | 306 | fp = fopen(filename, "rb"); 307 | if (!fp) 308 | return -1; 309 | 310 | //Get the size 311 | fseek(fp, 0, SEEK_END); 312 | fsize = ftell(fp); 313 | fseek(fp, 0, SEEK_SET); 314 | 315 | if(fsize > length) 316 | fsize = length; 317 | 318 | while (total < fsize) 319 | { 320 | num_read = fread(buffer + total, 1, fsize, fp); 321 | total += num_read; 322 | } 323 | 324 | fclose(fp); 325 | 326 | return fsize; 327 | } 328 | 329 | #ifdef KLEE 330 | #define FUZZ_BUFFER_SIZE 256 331 | #elif defined(KLEE_DEBUG) 332 | #define FUZZ_BUFFER_SIZE 256 333 | #else 334 | #define FUZZ_BUFFER_SIZE (64*1024) 335 | #endif 336 | 337 | 338 | static void run_test(char * buffer, int length, u16 family, struct inet_diag_entry * entry) { 339 | entry->family = family; 340 | entry->userlocks = 0; 341 | log("family %hu, userlocks %d\n", family, entry->userlocks); 342 | inet_diag_bc_run(buffer, length, entry); 343 | entry->userlocks = 1; 344 | log("family %hu, userlocks %d\n", family, entry->userlocks); 345 | inet_diag_bc_run(buffer, length, entry); 346 | } 347 | 348 | int main(int argc, char **argv) 349 | { 350 | struct x509_certificate * cert; 351 | char * fuzz_filename; 352 | int fuzz_length; 353 | struct inet_diag_entry entry; 354 | __be32 saddr[32]; 355 | __be32 daddr[32]; 356 | char * fuzz_buffer; 357 | 358 | fuzz_buffer = malloc(FUZZ_BUFFER_SIZE); 359 | if(!fuzz_buffer) { 360 | printf("Failed to allocate fuzz buffer\n"); 361 | return 1; 362 | } 363 | 364 | #ifndef KLEE 365 | if(argc < 2) { 366 | printf("Usage: bc filename\n"); 367 | return 1; 368 | } 369 | fuzz_filename = argv[1]; 370 | #endif 371 | 372 | //Setup the fake entry 373 | memset(&entry, 0, sizeof(entry)); 374 | memset(&saddr, 0, sizeof(saddr)); 375 | memset(&daddr, 0, sizeof(daddr)); 376 | entry.saddr = (__be32 *)&saddr; 377 | entry.daddr = (__be32 *)&daddr; 378 | entry.sport = 16*1024; 379 | entry.dport = 32*1024; 380 | 381 | #ifdef __AFL_HAVE_MANUAL_CONTROL 382 | __AFL_INIT(); 383 | #endif 384 | 385 | #ifdef __AFL_LOOP 386 | while (__AFL_LOOP(1000)) { 387 | #endif 388 | 389 | memset(fuzz_buffer, 0, FUZZ_BUFFER_SIZE); 390 | 391 | #ifdef KLEE 392 | unsigned short size; 393 | klee_make_symbolic(&size, sizeof(short), "size"); 394 | size &= 0xff; 395 | 396 | klee_assume(size < FUZZ_BUFFER_SIZE); 397 | fuzz_length = size; 398 | if(fuzz_length == 0) 399 | return 1; 400 | 401 | klee_make_symbolic(fuzz_buffer, FUZZ_BUFFER_SIZE, "buffer"); 402 | 403 | #else 404 | 405 | fuzz_length = read_file(fuzz_filename, fuzz_buffer, FUZZ_BUFFER_SIZE); 406 | if(fuzz_length < 0) 407 | #ifdef __AFL_LOOP 408 | continue; 409 | #else 410 | return 1; 411 | #endif 412 | #endif 413 | 414 | if(inet_diag_bc_audit(fuzz_buffer, fuzz_length)) { 415 | log("Audit failed\n"); 416 | #ifdef __AFL_LOOP 417 | continue; 418 | #else 419 | return 1; 420 | #endif 421 | } 422 | 423 | run_test(fuzz_buffer, fuzz_length, AF_UNSPEC, &entry); 424 | run_test(fuzz_buffer, fuzz_length, AF_INET, &entry); 425 | run_test(fuzz_buffer, fuzz_length, AF_INET6, &entry); 426 | 427 | #ifdef __AFL_LOOP 428 | } 429 | #endif 430 | 431 | free(fuzz_buffer); 432 | 433 | return 0; 434 | } 435 | 436 | --------------------------------------------------------------------------------