├── .clang-format ├── .clang-tidy ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── documentation.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ ├── clang-format.yml │ ├── closed-issue-message.yml │ ├── handle-stale-discussions.yml │ ├── issue-regression-labeler.yml │ └── stale_issue.yml ├── .gitignore ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── bin ├── produce_x_platform_fuzz_corpus │ ├── CMakeLists.txt │ └── main.c ├── run_x_platform_fuzz_corpus │ ├── CMakeLists.txt │ └── main.c └── sha256_profile │ ├── CMakeLists.txt │ └── main.c ├── builder.json ├── cmake ├── aws-c-cal-config.cmake └── modules │ ├── Findcrypto.cmake │ └── aws-lc.cmake ├── ecdsa-fuzz-corpus ├── darwin │ └── p256_sig_corpus.txt └── windows │ └── p256_sig_corpus.txt ├── format-check.py ├── include └── aws │ └── cal │ ├── cal.h │ ├── ecc.h │ ├── ed25519.h │ ├── exports.h │ ├── hash.h │ ├── hmac.h │ ├── private │ ├── der.h │ ├── ecc.h │ ├── opensslcrypto_common.h │ ├── rsa.h │ └── symmetric_cipher_priv.h │ ├── rsa.h │ └── symmetric_cipher.h ├── source ├── cal.c ├── darwin │ ├── common_cryptor_spi.h │ ├── commoncrypto_aes.c │ ├── commoncrypto_hmac.c │ ├── commoncrypto_md5.c │ ├── commoncrypto_platform_init.c │ ├── commoncrypto_sha1.c │ ├── commoncrypto_sha256.c │ ├── securityframework_ecc.c │ └── securityframework_rsa.c ├── der.c ├── ecc.c ├── ed25519.c ├── hash.c ├── hmac.c ├── rsa.c ├── shared │ ├── ed25519.c │ ├── ed25519_noop.c │ └── lccrypto_common.c ├── symmetric_cipher.c ├── unix │ ├── openssl_aes.c │ ├── openssl_platform_init.c │ ├── openssl_rsa.c │ ├── opensslcrypto_ecc.c │ ├── opensslcrypto_hash.c │ └── opensslcrypto_hmac.c └── windows │ ├── bcrypt_aes.c │ ├── bcrypt_ecc.c │ ├── bcrypt_hash.c │ ├── bcrypt_hmac.c │ ├── bcrypt_platform_init.c │ └── bcrypt_rsa.c └── tests ├── CMakeLists.txt ├── aes256_test.c ├── der_test.c ├── ecc_test.c ├── ed25519_test.c ├── md5_test.c ├── rsa_test.c ├── sha1_test.c ├── sha256_hmac_test.c ├── sha256_test.c └── test_case_helper.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Mozilla 4 | AlignAfterOpenBracket: AlwaysBreak 5 | AlignConsecutiveAssignments: false 6 | AlignConsecutiveDeclarations: false 7 | AlignEscapedNewlines: Right 8 | AlignOperands: true 9 | AlignTrailingComments: true 10 | AllowAllParametersOfDeclarationOnNextLine: false 11 | AllowShortBlocksOnASingleLine: false 12 | AllowShortCaseLabelsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: Inline 14 | AllowShortIfStatementsOnASingleLine: false 15 | AllowShortLoopsOnASingleLine: false 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakBeforeMultilineStrings: false 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BreakBeforeBinaryOperators: None 21 | BreakBeforeBraces: Attach 22 | BreakBeforeTernaryOperators: true 23 | BreakStringLiterals: true 24 | ColumnLimit: 120 25 | ContinuationIndentWidth: 4 26 | DerivePointerAlignment: false 27 | IncludeBlocks: Preserve 28 | IndentCaseLabels: true 29 | IndentPPDirectives: AfterHash 30 | IndentWidth: 4 31 | IndentWrappedFunctionNames: true 32 | KeepEmptyLinesAtTheStartOfBlocks: true 33 | MacroBlockBegin: '' 34 | MacroBlockEnd: '' 35 | MaxEmptyLinesToKeep: 1 36 | PenaltyBreakAssignment: 2 37 | PenaltyBreakBeforeFirstCallParameter: 19 38 | PenaltyBreakComment: 300 39 | PenaltyBreakFirstLessLess: 120 40 | PenaltyBreakString: 1000 41 | PenaltyExcessCharacter: 1000000 42 | PenaltyReturnTypeOnItsOwnLine: 100000 43 | PointerAlignment: Right 44 | ReflowComments: true 45 | SortIncludes: true 46 | SpaceAfterCStyleCast: false 47 | SpaceBeforeAssignmentOperators: true 48 | SpaceBeforeParens: ControlStatements 49 | SpaceInEmptyParentheses: false 50 | SpacesInContainerLiterals: true 51 | SpacesInCStyleCastParentheses: false 52 | SpacesInParentheses: false 53 | SpacesInSquareBrackets: false 54 | Standard: Cpp11 55 | TabWidth: 4 56 | UseTab: Never 57 | ... 58 | 59 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: 'clang-diagnostic-*,clang-analyzer-*,readability-*,modernize-*,bugprone-*,misc-*,google-runtime-int,llvm-header-guard,fuchsia-restrict-system-includes,-clang-analyzer-valist.Uninitialized,-clang-analyzer-security.insecureAPI.rand,-clang-analyzer-alpha.*,-readability-magic-numbers,-readability-non-const-parameter' 3 | WarningsAsErrors: '*' 4 | HeaderFilterRegex: '.*(? 161 | $) 162 | # When we install, the generated header will be at the INSTALL_INTERFACE:include location, 163 | # but at build time we need to explicitly include this here 164 | target_include_directories(${PROJECT_NAME} PUBLIC 165 | $) 166 | 167 | aws_prepare_shared_lib_exports(${PROJECT_NAME}) 168 | 169 | configure_file("cmake/${PROJECT_NAME}-config.cmake" 170 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 171 | @ONLY) 172 | 173 | aws_check_headers(${PROJECT_NAME} ${AWS_CAL_HEADERS}) 174 | install(FILES ${AWS_CAL_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/aws/cal" COMPONENT Development) 175 | 176 | if (BUILD_SHARED_LIBS) 177 | set (TARGET_DIR "shared") 178 | else() 179 | set (TARGET_DIR "static") 180 | endif() 181 | 182 | install(EXPORT "${PROJECT_NAME}-targets" 183 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${TARGET_DIR}/" 184 | NAMESPACE AWS:: 185 | COMPONENT Development) 186 | 187 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 188 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 189 | COMPONENT Development) 190 | 191 | list(APPEND EXPORT_MODULES 192 | "cmake/modules/Findcrypto.cmake" 193 | ) 194 | 195 | install(FILES ${EXPORT_MODULES} 196 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/modules" 197 | COMPONENT Development) 198 | 199 | if (NOT CMAKE_CROSSCOMPILING AND NOT BYO_CRYPTO) 200 | include(CTest) 201 | if (BUILD_TESTING) 202 | add_subdirectory(bin/sha256_profile) 203 | add_subdirectory(bin/produce_x_platform_fuzz_corpus) 204 | add_subdirectory(bin/run_x_platform_fuzz_corpus) 205 | add_subdirectory(tests) 206 | endif() 207 | endif() 208 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/awslabs/aws-c-cal/issues), or [recently closed](https://github.com/awslabs/aws-c-cal/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/aws-c-cal/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/awslabs/aws-c-cal/blob/main/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | AWS C Cal 2 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | SPDX-License-Identifier: Apache-2.0. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AWS C Cal 2 | 3 | AWS Crypto Abstraction Layer: Cross-Platform, C99 wrapper for cryptography primitives. 4 | 5 | ## License 6 | 7 | This library is licensed under the Apache 2.0 License. 8 | 9 | ## Supported Platforms 10 | * Windows (Vista and Later) 11 | * Apple (MacOS 10.15+, IOS 11+) 12 | * Unix (via OpenSSL compatible libcrypto) 13 | 14 | ## Build Instructions 15 | 16 | CMake 3.9+ is required to build. 17 | 18 | `` must be an absolute path in the following instructions. 19 | 20 | #### Linux-Only Dependencies 21 | 22 | If you are building on Linux, there are several options for crypto libraries. 23 | Preferred choice is aws-lc, that can be build as follows. 24 | 25 | ``` 26 | git clone git@github.com:awslabs/aws-lc.git 27 | cmake -S aws-lc -B aws-lc/build -DCMAKE_INSTALL_PREFIX= 28 | cmake --build aws-lc/build --target install 29 | ``` 30 | 31 | Alternatively, OpenSSL versions 1.0.2 or 1.1.1 or BoringSSL at commit 9939e14 32 | (other commits are not tested and not guaranteed to work) can be used. To build 33 | against OpenSSL or BoringSSL specify -DUSE_OPENSSL=ON. Typical OpenSSL flags can 34 | be used to help project locate artifacts (-DLibCrypto_INCLUDE_DIR and -DLibCrypto_STATIC_LIBRARY) 35 | 36 | #### Building aws-c-cal and Remaining Dependencies 37 | 38 | ``` 39 | git clone git@github.com:awslabs/aws-c-common.git 40 | cmake -S aws-c-common -B aws-c-common/build -DCMAKE_INSTALL_PREFIX= 41 | cmake --build aws-c-common/build --target install 42 | 43 | git clone git@github.com:awslabs/aws-c-cal.git 44 | cmake -S aws-c-cal -B aws-c-cal/build -DCMAKE_INSTALL_PREFIX= -DCMAKE_PREFIX_PATH= 45 | cmake --build aws-c-cal/build --target install 46 | ``` 47 | 48 | ## Currently provided algorithms 49 | 50 | ### Hashes 51 | #### MD5 52 | ##### Streaming 53 | ```` 54 | struct aws_hash *hash = aws_md5_new(allocator); 55 | aws_hash_update(hash, &your_buffer); 56 | aws_hash_finalize(hash, &output_buffer, 0); 57 | aws_hash_destroy(hash); 58 | ```` 59 | 60 | ##### One-Shot 61 | ```` 62 | aws_md5_compute(allocator, &your_buffer, &output_buffer, 0); 63 | ```` 64 | 65 | #### SHA256 66 | ##### Streaming 67 | ```` 68 | struct aws_hash *hash = aws_sha256_new(allocator); 69 | aws_hash_update(hash, &your_buffer); 70 | aws_hash_finalize(hash, &output_buffer, 0); 71 | aws_hash_destroy(hash); 72 | ```` 73 | 74 | ##### One-Shot 75 | ```` 76 | aws_sha256_compute(allocator, &your_buffer, &output_buffer, 0); 77 | ```` 78 | 79 | ### HMAC 80 | #### SHA256 HMAC 81 | ##### Streaming 82 | ```` 83 | struct aws_hmac *hmac = aws_sha256_hmac_new(allocator, &secret_buf); 84 | aws_hmac_update(hmac, &your_buffer); 85 | aws_hmac_finalize(hmac, &output_buffer, 0); 86 | aws_hmac_destroy(hmac); 87 | ```` 88 | 89 | ##### One-Shot 90 | ```` 91 | aws_sha256_hmac_compute(allocator, &secret_buf, &your_buffer, &output_buffer, 0); 92 | ```` 93 | 94 | ## FAQ 95 | ### I want more algorithms, what do I do? 96 | Great! So do we! At a minimum, file an issue letting us know. If you want to file a Pull Request, we'd be happy to review and merge it when it's ready. 97 | ### Who should consume this package directly? 98 | Are you writing C directly? Then you should. 99 | Are you using any other programming language? This functionality will be exposed via that language specific crt packages. 100 | ### I found a security vulnerability in this package. What do I do? 101 | Due to the fact that this package is specifically performing cryptographic operations, please don't file a public issue. Instead, email aws-sdk-common-runtime@amazon.com, and we'll work with you directly. 102 | 103 | -------------------------------------------------------------------------------- /bin/produce_x_platform_fuzz_corpus/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | project(produce_x_platform_fuzz_corpus C) 3 | 4 | file(GLOB PROFILE_SRC 5 | "*.c" 6 | ) 7 | 8 | set(PROFILE_PROJECT_NAME produce_x_platform_fuzz_corpus) 9 | add_executable(${PROFILE_PROJECT_NAME} ${PROFILE_SRC}) 10 | aws_set_common_properties(${PROFILE_PROJECT_NAME}) 11 | 12 | target_include_directories(${PROFILE_PROJECT_NAME} PUBLIC 13 | $ 14 | $) 15 | 16 | target_link_libraries(${PROFILE_PROJECT_NAME} PRIVATE aws-c-cal) 17 | 18 | if (BUILD_SHARED_LIBS AND NOT WIN32) 19 | message(INFO " produce_x_platform_fuzz_corpus will be built with shared libs, but you may need to set LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib to run the application") 20 | endif() 21 | -------------------------------------------------------------------------------- /bin/produce_x_platform_fuzz_corpus/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | struct produce_corpus_ctx { 18 | struct aws_allocator *allocator; 19 | const char *root_path; 20 | }; 21 | 22 | static struct aws_cli_option s_long_options[] = { 23 | {"output-path", AWS_CLI_OPTIONS_REQUIRED_ARGUMENT, NULL, 'o'}, 24 | {"help", AWS_CLI_OPTIONS_NO_ARGUMENT, NULL, 'h'}, 25 | /* Per getopt(3) the last element of the array has to be filled with all zeros */ 26 | {NULL, AWS_CLI_OPTIONS_NO_ARGUMENT, NULL, 0}, 27 | }; 28 | 29 | static void s_usage(int exit_code) { 30 | 31 | fprintf(stderr, "usage: produce_x_platform_fuzz_corpus [options]\n"); 32 | fprintf(stderr, "\n Options:\n\n"); 33 | fprintf( 34 | stderr, " --output-path DIRECTORY: path to output corpus to, default is the current working directory.\n"); 35 | fprintf(stderr, " -h, --help\n"); 36 | fprintf(stderr, " Display this message and quit.\n"); 37 | exit(exit_code); 38 | } 39 | 40 | static void s_parse_options(int argc, char **argv, struct produce_corpus_ctx *ctx) { 41 | while (true) { 42 | int option_index = 0; 43 | int c = aws_cli_getopt_long(argc, argv, "o:h", s_long_options, &option_index); 44 | if (c == -1) { 45 | break; 46 | } 47 | 48 | switch (c) { 49 | case 0: 50 | /* getopt_long() returns 0 if an option.flag is non-null */ 51 | break; 52 | case 'o': 53 | ctx->root_path = aws_cli_optarg; 54 | break; 55 | case 'h': 56 | s_usage(0); 57 | break; 58 | default: 59 | fprintf(stderr, "Unknown option\n"); 60 | s_usage(1); 61 | } 62 | } 63 | } 64 | 65 | /** 66 | * Runs thousands of ECDSA signatures, and dumps them out to a file. This assumes the same public key and 67 | * message to sign scheme is used by the verifying program. 68 | */ 69 | int main(int argc, char *argv[]) { 70 | struct aws_allocator *allocator = aws_default_allocator(); 71 | aws_cal_library_init(allocator); 72 | 73 | struct produce_corpus_ctx ctx = { 74 | .allocator = allocator, 75 | }; 76 | 77 | s_parse_options(argc, argv, &ctx); 78 | 79 | struct aws_byte_buf output_path; 80 | aws_byte_buf_init(&output_path, allocator, 1024); 81 | struct aws_byte_cursor sub_dir_cur; 82 | 83 | if (ctx.root_path) { 84 | struct aws_byte_cursor root_path = aws_byte_cursor_from_c_str(ctx.root_path); 85 | aws_byte_buf_append_dynamic(&output_path, &root_path); 86 | 87 | if (root_path.ptr[root_path.len - 1] != AWS_PATH_DELIM) { 88 | aws_byte_buf_append_byte_dynamic(&output_path, (uint8_t)AWS_PATH_DELIM); 89 | } 90 | } 91 | 92 | #ifdef _WIN32 93 | sub_dir_cur = aws_byte_cursor_from_c_str("windows\\"); 94 | #elif __APPLE__ 95 | sub_dir_cur = aws_byte_cursor_from_c_str("darwin/"); 96 | #else 97 | sub_dir_cur = aws_byte_cursor_from_c_str("unix/"); 98 | #endif 99 | 100 | aws_byte_buf_append_dynamic(&output_path, &sub_dir_cur); 101 | struct aws_string *directory = aws_string_new_from_buf(allocator, &output_path); 102 | aws_directory_create(directory); 103 | aws_string_destroy(directory); 104 | 105 | struct aws_byte_cursor file_name = aws_byte_cursor_from_c_str("p256_sig_corpus.txt"); 106 | aws_byte_buf_append_dynamic(&output_path, &file_name); 107 | 108 | struct aws_string *path = aws_string_new_from_buf(allocator, &output_path); 109 | struct aws_string *mode = aws_string_new_from_c_str(allocator, "w"); 110 | FILE *output_file = aws_fopen_safe(path, mode); 111 | 112 | if (!output_file) { 113 | fprintf( 114 | stderr, 115 | "Error %s, while opening file to: %s\n", 116 | aws_error_debug_str(aws_last_error()), 117 | aws_string_c_str(path)); 118 | exit(-1); 119 | } 120 | 121 | aws_string_destroy(mode); 122 | aws_string_destroy(path); 123 | aws_byte_buf_clean_up(&output_path); 124 | 125 | /* use pre-built private/pub key pairs, we'll fuzz via the input. */ 126 | uint8_t d[] = { 127 | 0x51, 0x9b, 0x42, 0x3d, 0x71, 0x5f, 0x8b, 0x58, 0x1f, 0x4f, 0xa8, 0xee, 0x59, 0xf4, 0x77, 0x1a, 128 | 0x5b, 0x44, 0xc8, 0x13, 0x0b, 0x4e, 0x3e, 0xac, 0xca, 0x54, 0xa5, 0x6d, 0xda, 0x72, 0xb4, 0x64, 129 | }; 130 | 131 | struct aws_byte_cursor private_key = aws_byte_cursor_from_array(d, sizeof(d)); 132 | 133 | uint8_t x[] = { 134 | 0x1c, 0xcb, 0xe9, 0x1c, 0x07, 0x5f, 0xc7, 0xf4, 0xf0, 0x33, 0xbf, 0xa2, 0x48, 0xdb, 0x8f, 0xcc, 135 | 0xd3, 0x56, 0x5d, 0xe9, 0x4b, 0xbf, 0xb1, 0x2f, 0x3c, 0x59, 0xff, 0x46, 0xc2, 0x71, 0xbf, 0x83, 136 | }; 137 | 138 | uint8_t y[] = { 139 | 0xce, 0x40, 0x14, 0xc6, 0x88, 0x11, 0xf9, 0xa2, 0x1a, 0x1f, 0xdb, 0x2c, 0x0e, 0x61, 0x13, 0xe0, 140 | 0x6d, 0xb7, 0xca, 0x93, 0xb7, 0x40, 0x4e, 0x78, 0xdc, 0x7c, 0xcd, 0x5c, 0xa8, 0x9a, 0x4c, 0xa9, 141 | }; 142 | 143 | struct aws_byte_cursor pub_x = aws_byte_cursor_from_array(x, sizeof(x)); 144 | struct aws_byte_cursor pub_y = aws_byte_cursor_from_array(y, sizeof(y)); 145 | 146 | struct aws_ecc_key_pair *signing_key = 147 | aws_ecc_key_pair_new_from_private_key(allocator, AWS_CAL_ECDSA_P256, &private_key); 148 | struct aws_ecc_key_pair *verifying_key = 149 | aws_ecc_key_pair_new_from_public_key(allocator, AWS_CAL_ECDSA_P256, &pub_x, &pub_y); 150 | 151 | struct aws_byte_buf raw_buf; 152 | aws_byte_buf_init(&raw_buf, allocator, 1024); 153 | 154 | size_t max_iterations = 10000; 155 | size_t count = 0; 156 | 157 | struct aws_byte_cursor to_append = aws_byte_cursor_from_c_str("a"); 158 | struct aws_byte_buf to_sign; 159 | aws_byte_buf_init(&to_sign, allocator, AWS_SHA256_LEN); 160 | 161 | struct aws_byte_buf signature_output; 162 | aws_byte_buf_init(&signature_output, allocator, aws_ecc_key_pair_signature_length(signing_key)); 163 | 164 | struct aws_byte_buf hex_buf; 165 | aws_byte_buf_init(&hex_buf, allocator, 1024); 166 | 167 | for (; count < max_iterations; ++count) { 168 | struct aws_byte_cursor hash_input = aws_byte_cursor_from_buf(&raw_buf); 169 | 170 | aws_sha256_compute(allocator, &hash_input, &to_sign, 0); 171 | struct aws_byte_cursor signing_cur = aws_byte_cursor_from_buf(&to_sign); 172 | 173 | int signing_val = aws_ecc_key_pair_sign_message(signing_key, &signing_cur, &signature_output); 174 | (void)signing_val; 175 | 176 | struct aws_byte_cursor signature_cur = aws_byte_cursor_from_buf(&signature_output); 177 | int verify_val = aws_ecc_key_pair_verify_signature(verifying_key, &signing_cur, &signature_cur); 178 | 179 | aws_hex_encode(&signature_cur, &hex_buf); 180 | struct aws_byte_cursor hex_encoded_cur = aws_byte_cursor_from_buf(&hex_buf); 181 | 182 | if (verify_val != AWS_OP_SUCCESS) { 183 | fprintf( 184 | stderr, 185 | "Signature: \"" PRInSTR "\" was produced but could not be verified\n", 186 | AWS_BYTE_CURSOR_PRI(hex_encoded_cur)); 187 | } 188 | 189 | fprintf(output_file, PRInSTR "\n", AWS_BYTE_CURSOR_PRI(hex_encoded_cur)); 190 | 191 | aws_byte_buf_append_dynamic(&raw_buf, &to_append); 192 | aws_byte_buf_reset(&hex_buf, true); 193 | aws_byte_buf_reset(&to_sign, true); 194 | aws_byte_buf_reset(&signature_output, true); 195 | } 196 | 197 | aws_byte_buf_clean_up(&hex_buf); 198 | aws_byte_buf_clean_up(&signature_output); 199 | aws_byte_buf_clean_up(&raw_buf); 200 | 201 | aws_ecc_key_pair_release(verifying_key); 202 | aws_ecc_key_pair_release(signing_key); 203 | 204 | fclose(output_file); 205 | 206 | aws_cal_library_clean_up(); 207 | return 0; 208 | } 209 | -------------------------------------------------------------------------------- /bin/run_x_platform_fuzz_corpus/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | project(run_x_platform_fuzz_corpus C) 3 | 4 | file(GLOB PROFILE_SRC 5 | "*.c" 6 | ) 7 | 8 | set(PROFILE_PROJECT_NAME run_x_platform_fuzz_corpus) 9 | add_executable(${PROFILE_PROJECT_NAME} ${PROFILE_SRC}) 10 | aws_set_common_properties(${PROFILE_PROJECT_NAME}) 11 | 12 | target_include_directories(${PROFILE_PROJECT_NAME} PUBLIC 13 | $ 14 | $) 15 | 16 | target_link_libraries(${PROFILE_PROJECT_NAME} PRIVATE aws-c-cal) 17 | 18 | if (BUILD_SHARED_LIBS AND NOT WIN32) 19 | message(INFO " run_x_platform_fuzz_corpus will be built with shared libs, but you may need to set LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib to run the application") 20 | endif() 21 | -------------------------------------------------------------------------------- /bin/run_x_platform_fuzz_corpus/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | struct run_corpus_ctx { 18 | struct aws_allocator *allocator; 19 | const char *root_path; 20 | }; 21 | 22 | static struct aws_cli_option s_long_options[] = { 23 | {"corpus-path", AWS_CLI_OPTIONS_REQUIRED_ARGUMENT, NULL, 'o'}, 24 | {"help", AWS_CLI_OPTIONS_NO_ARGUMENT, NULL, 'h'}, 25 | /* Per getopt(3) the last element of the array has to be filled with all zeros */ 26 | {NULL, AWS_CLI_OPTIONS_NO_ARGUMENT, NULL, 0}, 27 | }; 28 | 29 | static void s_usage(int exit_code) { 30 | 31 | fprintf(stderr, "usage: run_x_platform_fuzz_corpus [options]\n"); 32 | fprintf(stderr, "\n Options:\n\n"); 33 | fprintf( 34 | stderr, 35 | " --corpus-path DIRECTORY: path to scan for corpus files default is the current working directory.\n"); 36 | fprintf(stderr, " -h, --help\n"); 37 | fprintf(stderr, " Display this message and quit.\n"); 38 | exit(exit_code); 39 | } 40 | 41 | static void s_parse_options(int argc, char **argv, struct run_corpus_ctx *ctx) { 42 | while (true) { 43 | int option_index = 0; 44 | int c = aws_cli_getopt_long(argc, argv, "o:h", s_long_options, &option_index); 45 | if (c == -1) { 46 | break; 47 | } 48 | 49 | switch (c) { 50 | case 0: 51 | /* getopt_long() returns 0 if an option.flag is non-null */ 52 | break; 53 | case 'o': 54 | ctx->root_path = aws_cli_optarg; 55 | break; 56 | case 'h': 57 | s_usage(0); 58 | break; 59 | default: 60 | fprintf(stderr, "Unknown option\n"); 61 | s_usage(1); 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * Attempts to load a corpus directory. If it's successful, it loads each platform's ECDSA corpus, and makes sure 68 | * it can actually verify the signatures in it provided the same key and message to sign are used as those used 69 | * to produce the signature. 70 | */ 71 | int main(int argc, char *argv[]) { 72 | struct aws_allocator *allocator = aws_default_allocator(); 73 | aws_cal_library_init(allocator); 74 | 75 | struct run_corpus_ctx ctx = { 76 | .allocator = allocator, 77 | }; 78 | 79 | s_parse_options(argc, argv, &ctx); 80 | 81 | uint8_t x[] = { 82 | 0x1c, 0xcb, 0xe9, 0x1c, 0x07, 0x5f, 0xc7, 0xf4, 0xf0, 0x33, 0xbf, 0xa2, 0x48, 0xdb, 0x8f, 0xcc, 83 | 0xd3, 0x56, 0x5d, 0xe9, 0x4b, 0xbf, 0xb1, 0x2f, 0x3c, 0x59, 0xff, 0x46, 0xc2, 0x71, 0xbf, 0x83, 84 | }; 85 | 86 | uint8_t y[] = { 87 | 0xce, 0x40, 0x14, 0xc6, 0x88, 0x11, 0xf9, 0xa2, 0x1a, 0x1f, 0xdb, 0x2c, 0x0e, 0x61, 0x13, 0xe0, 88 | 0x6d, 0xb7, 0xca, 0x93, 0xb7, 0x40, 0x4e, 0x78, 0xdc, 0x7c, 0xcd, 0x5c, 0xa8, 0x9a, 0x4c, 0xa9, 89 | }; 90 | 91 | struct aws_byte_cursor pub_x = aws_byte_cursor_from_array(x, sizeof(x)); 92 | struct aws_byte_cursor pub_y = aws_byte_cursor_from_array(y, sizeof(y)); 93 | 94 | struct aws_ecc_key_pair *verifying_key = 95 | aws_ecc_key_pair_new_from_public_key(allocator, AWS_CAL_ECDSA_P256, &pub_x, &pub_y); 96 | 97 | struct aws_byte_buf scan_path; 98 | aws_byte_buf_init(&scan_path, allocator, 1024); 99 | 100 | if (ctx.root_path) { 101 | struct aws_byte_cursor root_path = aws_byte_cursor_from_c_str(ctx.root_path); 102 | aws_byte_buf_append_dynamic(&scan_path, &root_path); 103 | 104 | /* if (root_path.ptr[root_path.len - 1] != AWS_PATH_DELIM) { 105 | aws_byte_buf_append_byte_dynamic(&scan_path, (uint8_t)AWS_PATH_DELIM); 106 | }*/ 107 | } 108 | 109 | struct aws_string *scan_path_str = aws_string_new_from_buf(allocator, &scan_path); 110 | struct aws_directory_iterator *dir_iter = aws_directory_entry_iterator_new(allocator, scan_path_str); 111 | 112 | if (!dir_iter) { 113 | fprintf(stderr, "Unable to load fuzz corpus from %s\n", aws_string_c_str(scan_path_str)); 114 | exit(-1); 115 | } 116 | 117 | struct aws_byte_cursor corpus_file_name = aws_byte_cursor_from_c_str("p256_sig_corpus.txt"); 118 | size_t corpus_runs = 0; 119 | const struct aws_directory_entry *entry = aws_directory_entry_iterator_get_value(dir_iter); 120 | while (entry) { 121 | struct aws_string *corpus_file = NULL; 122 | 123 | if (entry->file_type & AWS_FILE_TYPE_DIRECTORY) { 124 | struct aws_string *potential_corpus_path = aws_string_new_from_cursor(allocator, &entry->path); 125 | struct aws_directory_iterator *potential_corpus_dir = 126 | aws_directory_entry_iterator_new(allocator, potential_corpus_path); 127 | 128 | if (potential_corpus_dir) { 129 | const struct aws_directory_entry *corpus_file_candidate = 130 | aws_directory_entry_iterator_get_value(potential_corpus_dir); 131 | 132 | while (corpus_file_candidate) { 133 | struct aws_byte_cursor find_unused; 134 | if (aws_byte_cursor_find_exact( 135 | &corpus_file_candidate->relative_path, &corpus_file_name, &find_unused) == AWS_OP_SUCCESS) { 136 | corpus_file = aws_string_new_from_cursor(allocator, &corpus_file_candidate->path); 137 | break; 138 | } 139 | 140 | if (aws_directory_entry_iterator_next(potential_corpus_dir) != AWS_OP_SUCCESS) { 141 | break; 142 | } 143 | 144 | corpus_file_candidate = aws_directory_entry_iterator_get_value(potential_corpus_dir); 145 | } 146 | 147 | aws_directory_entry_iterator_destroy(potential_corpus_dir); 148 | } 149 | 150 | aws_string_destroy(potential_corpus_path); 151 | } 152 | 153 | if (corpus_file) { 154 | corpus_runs++; 155 | fprintf(stdout, "Running corpus file found at %s:\n\n", aws_string_c_str(corpus_file)); 156 | struct aws_string *mode = aws_string_new_from_c_str(allocator, "r"); 157 | FILE *corpus_input_file = aws_fopen_safe(corpus_file, mode); 158 | 159 | if (!corpus_input_file) { 160 | fprintf(stderr, "Unable to open file at %s\n", aws_string_c_str(corpus_file)); 161 | exit(-1); 162 | } 163 | 164 | struct aws_byte_buf hex_decoded_buf; 165 | aws_byte_buf_init(&hex_decoded_buf, allocator, 1024); 166 | 167 | struct aws_byte_cursor to_append = aws_byte_cursor_from_c_str("a"); 168 | struct aws_byte_buf signed_value; 169 | aws_byte_buf_init(&signed_value, allocator, AWS_SHA256_LEN); 170 | 171 | struct aws_byte_buf to_hash; 172 | aws_byte_buf_init(&to_hash, allocator, 1024); 173 | 174 | char line_buf[1024]; 175 | AWS_ZERO_ARRAY(line_buf); 176 | size_t signatures_processed = 0; 177 | size_t signatures_failed = 0; 178 | 179 | while (fgets(line_buf, 1024, corpus_input_file)) { 180 | 181 | /* -1 to strip off the newline delimiter */ 182 | struct aws_byte_cursor line_cur = aws_byte_cursor_from_c_str(line_buf); 183 | line_cur.len -= 1; 184 | 185 | if (aws_hex_decode(&line_cur, &hex_decoded_buf) != AWS_OP_SUCCESS) { 186 | fprintf( 187 | stderr, 188 | "Invalid line in file detected. Could not hex decode.\n Line is " PRInSTR "\n", 189 | AWS_BYTE_CURSOR_PRI(line_cur)); 190 | exit(-1); 191 | } 192 | 193 | struct aws_byte_cursor to_hash_cur = aws_byte_cursor_from_buf(&to_hash); 194 | aws_sha256_compute(allocator, &to_hash_cur, &signed_value, 0); 195 | 196 | struct aws_byte_cursor signed_value_cur = aws_byte_cursor_from_buf(&signed_value); 197 | struct aws_byte_cursor signature_cur = aws_byte_cursor_from_buf(&hex_decoded_buf); 198 | 199 | if (aws_ecc_key_pair_verify_signature(verifying_key, &signed_value_cur, &signature_cur)) { 200 | struct aws_byte_buf hex_encoded_sha; 201 | aws_byte_buf_init(&hex_encoded_sha, allocator, 1024); 202 | 203 | aws_hex_encode(&signed_value_cur, &hex_encoded_sha); 204 | struct aws_byte_cursor failed_sha = aws_byte_cursor_from_buf(&hex_encoded_sha); 205 | 206 | fprintf( 207 | stderr, 208 | "Failed to validate signature\n signature: " PRInSTR "\n message_signed: " PRInSTR "\n\n", 209 | AWS_BYTE_CURSOR_PRI(line_cur), 210 | AWS_BYTE_CURSOR_PRI(failed_sha)); 211 | signatures_failed++; 212 | aws_byte_buf_clean_up(&hex_encoded_sha); 213 | } 214 | 215 | aws_byte_buf_reset(&hex_decoded_buf, true); 216 | aws_byte_buf_reset(&signed_value, true); 217 | 218 | aws_byte_buf_append_dynamic(&to_hash, &to_append); 219 | AWS_ZERO_ARRAY(line_buf); 220 | signatures_processed++; 221 | } 222 | fprintf( 223 | stdout, 224 | "Corpus %d verification complete with %d failures out of %d signatures processed\n\n", 225 | (int)corpus_runs, 226 | (int)signatures_failed, 227 | (int)signatures_processed); 228 | 229 | aws_byte_buf_clean_up(&hex_decoded_buf); 230 | aws_byte_buf_clean_up(&to_hash); 231 | aws_byte_buf_clean_up(&signed_value); 232 | 233 | fclose(corpus_input_file); 234 | aws_string_destroy(mode); 235 | } 236 | 237 | aws_string_destroy(corpus_file); 238 | 239 | if (aws_directory_entry_iterator_next(dir_iter)) { 240 | break; 241 | } 242 | 243 | entry = aws_directory_entry_iterator_get_value(dir_iter); 244 | } 245 | aws_directory_entry_iterator_destroy(dir_iter); 246 | aws_string_destroy(scan_path_str); 247 | 248 | aws_byte_buf_clean_up(&scan_path); 249 | 250 | aws_ecc_key_pair_release(verifying_key); 251 | 252 | aws_cal_library_clean_up(); 253 | return 0; 254 | } 255 | -------------------------------------------------------------------------------- /bin/sha256_profile/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | project(sha256_profile C) 3 | 4 | file(GLOB PROFILE_SRC 5 | "*.c" 6 | ) 7 | 8 | set(PROFILE_PROJECT_NAME sha256_profile) 9 | add_executable(${PROFILE_PROJECT_NAME} ${PROFILE_SRC}) 10 | aws_set_common_properties(${PROFILE_PROJECT_NAME}) 11 | 12 | target_include_directories(${PROFILE_PROJECT_NAME} PUBLIC 13 | $ 14 | $) 15 | 16 | target_link_libraries(${PROFILE_PROJECT_NAME} PRIVATE aws-c-cal) 17 | 18 | if (BUILD_SHARED_LIBS AND NOT WIN32) 19 | message(INFO " sha256_profile will be built with shared libs, but you may need to set LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib to run the application") 20 | endif() 21 | -------------------------------------------------------------------------------- /bin/sha256_profile/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | static void s_profile_streaming_hash_at_chunk_size( 15 | struct aws_allocator *allocator, 16 | struct aws_byte_cursor to_hash, 17 | size_t chunk_size, 18 | size_t alignment) { 19 | struct aws_hash *hash_impl = aws_sha256_new(allocator); 20 | AWS_FATAL_ASSERT(hash_impl); 21 | 22 | struct aws_byte_buf output_buf; 23 | AWS_FATAL_ASSERT( 24 | !aws_byte_buf_init(&output_buf, allocator, AWS_SHA256_LEN) && "allocation of output buffer failed!"); 25 | 26 | struct aws_byte_cursor to_hash_seeked = to_hash; 27 | 28 | uint64_t start = 0; 29 | AWS_FATAL_ASSERT(!aws_high_res_clock_get_ticks(&start) && "clock get ticks failed."); 30 | 31 | if (alignment) { 32 | size_t alignment_miss = (uintptr_t)to_hash_seeked.ptr % alignment; 33 | struct aws_byte_cursor unaligned_chunk = aws_byte_cursor_advance(&to_hash_seeked, alignment_miss); 34 | AWS_FATAL_ASSERT(!aws_hash_update(hash_impl, &unaligned_chunk) && "hash compute of unaligned chunk failed"); 35 | } 36 | 37 | while (to_hash_seeked.len) { 38 | size_t remaining = chunk_size > to_hash_seeked.len ? to_hash_seeked.len : chunk_size; 39 | 40 | struct aws_byte_cursor chunk_to_process = aws_byte_cursor_advance(&to_hash_seeked, remaining); 41 | AWS_FATAL_ASSERT(!aws_hash_update(hash_impl, &chunk_to_process) && "hash compute of chunk failed"); 42 | } 43 | 44 | AWS_FATAL_ASSERT(!aws_hash_finalize(hash_impl, &output_buf, 0) && "hash finalize failed"); 45 | uint64_t end = 0; 46 | AWS_FATAL_ASSERT(!aws_high_res_clock_get_ticks(&end) && "clock get ticks failed"); 47 | fprintf(stdout, "SHA256 streaming computation took %" PRIu64 "ns\n", end - start); 48 | 49 | aws_byte_buf_clean_up(&output_buf); 50 | aws_hash_destroy(hash_impl); 51 | } 52 | 53 | static void s_profile_oneshot_hash(struct aws_allocator *allocator, struct aws_byte_cursor to_hash) { 54 | struct aws_byte_buf output_buf; 55 | 56 | AWS_FATAL_ASSERT( 57 | !aws_byte_buf_init(&output_buf, allocator, AWS_SHA256_LEN) && "allocation of output buffer failed!"); 58 | 59 | uint64_t start = 0; 60 | AWS_FATAL_ASSERT(!aws_high_res_clock_get_ticks(&start) && "clock get ticks failed."); 61 | AWS_FATAL_ASSERT(!aws_sha256_compute(allocator, &to_hash, &output_buf, 0) && "Hash computation failed"); 62 | uint64_t end = 0; 63 | AWS_FATAL_ASSERT(!aws_high_res_clock_get_ticks(&end) && "clock get ticks failed"); 64 | fprintf(stdout, "SHA256 oneshot computation took %" PRIu64 "ns\n", end - start); 65 | aws_byte_buf_clean_up(&output_buf); 66 | } 67 | 68 | static void s_run_profiles(struct aws_allocator *allocator, size_t to_hash_size, const char *profile_name) { 69 | fprintf(stdout, "********************* SHA256 Profile %s ************************************\n\n", profile_name); 70 | 71 | struct aws_byte_buf to_hash; 72 | AWS_FATAL_ASSERT(!aws_byte_buf_init(&to_hash, allocator, to_hash_size) && "failed to allocate buffer for hashing"); 73 | AWS_FATAL_ASSERT(!aws_device_random_buffer(&to_hash) && "reading random data failed"); 74 | struct aws_byte_cursor to_hash_cur = aws_byte_cursor_from_buf(&to_hash); 75 | 76 | fprintf(stdout, "********************* Chunked/Alignment Runs *********************************\n\n"); 77 | fprintf(stdout, "****** 128 byte chunks ******\n\n"); 78 | fprintf(stdout, "8-byte alignment:\n"); 79 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 128, 8); 80 | fprintf(stdout, "16-byte alignment:\n"); 81 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 128, 16); 82 | fprintf(stdout, "64-byte alignment:\n"); 83 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 128, 64); 84 | fprintf(stdout, "128-byte alignment:\n"); 85 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 128, 128); 86 | fprintf(stdout, "\n****** 256 byte chunks ******\n\n"); 87 | fprintf(stdout, "8-byte alignment:\n"); 88 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 256, 8); 89 | fprintf(stdout, "16-byte alignment:\n"); 90 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 256, 16); 91 | fprintf(stdout, "64-byte alignment:\n"); 92 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 256, 64); 93 | fprintf(stdout, "128-byte alignment:\n"); 94 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 256, 128); 95 | 96 | fprintf(stdout, "\n******* 512 byte chunks *****\n\n"); 97 | fprintf(stdout, "8-byte alignment:\n"); 98 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 512, 8); 99 | fprintf(stdout, "16-byte alignment:\n"); 100 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 512, 16); 101 | fprintf(stdout, "64-byte alignment:\n"); 102 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 512, 64); 103 | fprintf(stdout, "128-byte alignment:\n"); 104 | s_profile_streaming_hash_at_chunk_size(allocator, to_hash_cur, 512, 128); 105 | 106 | fprintf(stdout, "\n********************** Oneshot Run *******************************************\n\n"); 107 | s_profile_oneshot_hash(allocator, to_hash_cur); 108 | fprintf(stdout, "\n\n"); 109 | aws_byte_buf_clean_up(&to_hash); 110 | } 111 | 112 | int main(void) { 113 | struct aws_allocator *allocator = aws_default_allocator(); 114 | aws_cal_library_init(allocator); 115 | 116 | struct aws_hash *hash_impl = aws_sha256_new(allocator); 117 | fprintf(stdout, "Starting profile run for Sha256 using implementation %s\n\n", hash_impl->vtable->provider); 118 | s_run_profiles(allocator, 1024, "1 KB"); 119 | s_run_profiles(allocator, 1024 * 64, "64 KB"); 120 | s_run_profiles(allocator, 1024 * 128, "128 KB"); 121 | s_run_profiles(allocator, 1024 * 512, "512 KB"); 122 | 123 | aws_hash_destroy(hash_impl); 124 | aws_cal_library_clean_up(); 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /builder.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-c-cal", 3 | "upstream": [ 4 | { "name": "aws-c-common" } 5 | ], 6 | "downstream": [ 7 | { 8 | "name": "aws-c-io" 9 | }, 10 | { 11 | "name": "aws-c-auth" 12 | } 13 | ], 14 | "targets": { 15 | "linux": { 16 | "upstream": [ 17 | { 18 | "name": "aws-lc" 19 | } 20 | ] 21 | }, 22 | "android": { 23 | "upstream": [ 24 | { 25 | "name": "aws-lc" 26 | } 27 | ] 28 | }, 29 | "freebsd": { 30 | "upstream": [ 31 | { 32 | "name": "aws-lc" 33 | } 34 | ] 35 | }, 36 | "openbsd": { 37 | "upstream": [ 38 | { 39 | "name": "aws-lc" 40 | } 41 | ] 42 | }, 43 | "windows": { 44 | "!test_steps": [ 45 | "test", 46 | "{build_dir}/aws-c-cal/bin/sha256_profile/RelWithDebInfo/sha256_profile.exe", 47 | "{build_dir}/aws-c-cal/bin/run_x_platform_fuzz_corpus/RelWithDebInfo/run_x_platform_fuzz_corpus.exe --corpus-path {source_dir}/ecdsa-fuzz-corpus" 48 | ] 49 | } 50 | }, 51 | "variants": { 52 | "openssl": { 53 | "hosts": { 54 | "ubuntu": { 55 | "packages": [ 56 | "libssl-dev" 57 | ] 58 | } 59 | }, 60 | "targets": { 61 | "linux": { 62 | "!upstream": [ 63 | { "name": "aws-c-common" } 64 | ] 65 | } 66 | } 67 | }, 68 | "ancient-openssl": { 69 | "hosts": { 70 | "ubuntu": { 71 | "packages": [ 72 | "libssl1.0-dev", 73 | "libssl1.0.0" 74 | ] 75 | } 76 | }, 77 | "targets": { 78 | "linux": { 79 | "!upstream": [ 80 | { "name": "aws-c-common" } 81 | ] 82 | } 83 | } 84 | }, 85 | "boringssl": { 86 | "hosts": { 87 | "ubuntu": { 88 | "packages": [ 89 | "golang-go" 90 | ] 91 | } 92 | }, 93 | "targets": { 94 | "linux": { 95 | "!upstream": [ 96 | { 97 | "name": "aws-c-common" 98 | }, 99 | { 100 | "name": "boringssl", 101 | "revision": "9939e14" 102 | } 103 | ] 104 | } 105 | } 106 | }, 107 | "aws-lc-fips": { 108 | "targets": { 109 | "linux": { 110 | "!upstream": [ 111 | { 112 | "name": "aws-c-common" 113 | }, 114 | { 115 | "name": "aws-lc", 116 | "_comment": "FIPS releases are currently cut from this branch", 117 | "revision": "fips-2022-11-02" 118 | } 119 | ] 120 | } 121 | } 122 | }, 123 | "aws-lc-ed25519": { 124 | "targets": { 125 | "windows": { 126 | "+upstream": [ 127 | { 128 | "name": "aws-lc" 129 | } 130 | ] 131 | }, 132 | "macos": { 133 | "+upstream": [ 134 | { 135 | "name": "aws-lc" 136 | } 137 | ] 138 | } 139 | } 140 | }, 141 | "no-tests": { 142 | "!test_steps": [] 143 | }, 144 | "just-tests": { 145 | "!test_steps": [ 146 | "test" 147 | ] 148 | } 149 | }, 150 | "test_steps": [ 151 | "test", 152 | [ 153 | "{build_dir}/aws-c-cal/bin/sha256_profile/sha256_profile" 154 | ], 155 | "{build_dir}/aws-c-cal/bin/run_x_platform_fuzz_corpus/run_x_platform_fuzz_corpus --corpus-path {source_dir}/ecdsa-fuzz-corpus" 156 | 157 | ] 158 | } 159 | -------------------------------------------------------------------------------- /cmake/aws-c-cal-config.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | find_dependency(aws-c-common) 4 | 5 | if (NOT @BYO_CRYPTO@ AND (@AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE@ OR (NOT WIN32 AND NOT APPLE))) 6 | if (@USE_OPENSSL@ AND NOT ANDROID) 7 | # aws-c-cal has been built with a dependency on OpenSSL::Crypto, 8 | # therefore consumers of this library have a dependency on OpenSSL and must have it found 9 | find_dependency(OpenSSL REQUIRED) 10 | find_dependency(Threads REQUIRED) 11 | else() 12 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules") 13 | find_dependency(crypto) 14 | endif() 15 | endif() 16 | 17 | macro(aws_load_targets type) 18 | include(${CMAKE_CURRENT_LIST_DIR}/${type}/@PROJECT_NAME@-targets.cmake) 19 | endmacro() 20 | 21 | # try to load the lib follow BUILD_SHARED_LIBS. Fall back if not exist. 22 | if (BUILD_SHARED_LIBS) 23 | if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/shared") 24 | aws_load_targets(shared) 25 | else() 26 | aws_load_targets(static) 27 | endif() 28 | else() 29 | if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/static") 30 | aws_load_targets(static) 31 | else() 32 | aws_load_targets(shared) 33 | endif() 34 | endif() 35 | -------------------------------------------------------------------------------- /cmake/modules/Findcrypto.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find LibCrypto include dirs and libraries 2 | # 3 | # Usage of this module as follows: 4 | # 5 | # find_package(crypto) 6 | # 7 | # Variables used by this module, they can change the default behaviour and need 8 | # to be set before calling find_package: 9 | # 10 | # Variables defined by this module: 11 | # 12 | # crypto_FOUND System has libcrypto, include and library dirs found 13 | # crypto_INCLUDE_DIR The crypto include directories. 14 | # crypto_LIBRARY The crypto library, depending on the value of BUILD_SHARED_LIBS. 15 | # crypto_SHARED_LIBRARY The path to libcrypto.so 16 | # crypto_STATIC_LIBRARY The path to libcrypto.a 17 | # crypto_STATIC_LIBRARY The path to libcrypto.a 18 | 19 | # the next branch exists purely for cmake compatibility with versions older than 3.15. Please do not remove it before 20 | # we baseline on a newer version. It does not like duplicate target declarations. Work around that by checking it isn't 21 | # defined first. 22 | if (TARGET crypto OR TARGET AWS::crypto) 23 | if (TARGET crypto) 24 | set(TARGET_NAME "crypto") 25 | else() 26 | set(TARGET_NAME "AWS::crypto") 27 | endif() 28 | 29 | get_target_property(crypto_INCLUDE_DIR ${TARGET_NAME} INTERFACE_INCLUDE_DIRECTORIES) 30 | message(STATUS "aws-c-cal found target: ${TARGET_NAME}") 31 | message(STATUS "crypto Include Dir: ${crypto_INCLUDE_DIR}") 32 | set(CRYPTO_FOUND true) 33 | set(crypto_FOUND true) 34 | else() 35 | 36 | find_path(crypto_INCLUDE_DIR 37 | NAMES openssl/crypto.h 38 | HINTS 39 | ${CMAKE_PREFIX_PATH}/include 40 | ${CMAKE_INSTALL_PREFIX}/include 41 | ) 42 | 43 | find_library(crypto_SHARED_LIBRARY 44 | NAMES libcrypto.so libcrypto.dylib crypto.dll 45 | HINTS 46 | ${CMAKE_PREFIX_PATH}/build/crypto 47 | ${CMAKE_PREFIX_PATH}/build 48 | ${CMAKE_PREFIX_PATH} 49 | ${CMAKE_PREFIX_PATH}/lib64 50 | ${CMAKE_PREFIX_PATH}/lib 51 | ${CMAKE_INSTALL_PREFIX}/build/crypto 52 | ${CMAKE_INSTALL_PREFIX}/build 53 | ${CMAKE_INSTALL_PREFIX} 54 | ${CMAKE_INSTALL_PREFIX}/lib64 55 | ${CMAKE_INSTALL_PREFIX}/lib 56 | ) 57 | 58 | find_library(crypto_STATIC_LIBRARY 59 | NAMES libcrypto.a crypto.lib 60 | HINTS 61 | ${CMAKE_PREFIX_PATH}/build/crypto 62 | ${CMAKE_PREFIX_PATH}/build 63 | ${CMAKE_PREFIX_PATH} 64 | ${CMAKE_PREFIX_PATH}/lib64 65 | ${CMAKE_PREFIX_PATH}/lib 66 | ${CMAKE_INSTALL_PREFIX}/build/crypto 67 | ${CMAKE_INSTALL_PREFIX}/build 68 | ${CMAKE_INSTALL_PREFIX} 69 | ${CMAKE_INSTALL_PREFIX}/lib64 70 | ${CMAKE_INSTALL_PREFIX}/lib 71 | ) 72 | 73 | if (BUILD_SHARED_LIBS OR AWS_USE_CRYPTO_SHARED_LIBS) 74 | if (crypto_SHARED_LIBRARY) 75 | set(crypto_LIBRARY ${crypto_SHARED_LIBRARY}) 76 | else() 77 | set(crypto_LIBRARY ${crypto_STATIC_LIBRARY}) 78 | endif() 79 | else() 80 | if (crypto_STATIC_LIBRARY) 81 | set(crypto_LIBRARY ${crypto_STATIC_LIBRARY}) 82 | else() 83 | set(crypto_LIBRARY ${crypto_SHARED_LIBRARY}) 84 | endif() 85 | endif() 86 | 87 | include(FindPackageHandleStandardArgs) 88 | find_package_handle_standard_args(crypto DEFAULT_MSG 89 | crypto_LIBRARY 90 | crypto_INCLUDE_DIR 91 | ) 92 | 93 | mark_as_advanced( 94 | crypto_ROOT_DIR 95 | crypto_INCLUDE_DIR 96 | crypto_LIBRARY 97 | crypto_SHARED_LIBRARY 98 | crypto_STATIC_LIBRARY 99 | ) 100 | 101 | # some versions of cmake have a super esoteric bug around capitalization differences between 102 | # find dependency and find package, just avoid that here by checking and 103 | # setting both. 104 | if(CRYPTO_FOUND OR crypto_FOUND) 105 | set(CRYPTO_FOUND true) 106 | set(crypto_FOUND true) 107 | 108 | message(STATUS "LibCrypto Include Dir: ${crypto_INCLUDE_DIR}") 109 | message(STATUS "LibCrypto Shared Lib: ${crypto_SHARED_LIBRARY}") 110 | message(STATUS "LibCrypto Static Lib: ${crypto_STATIC_LIBRARY}") 111 | if (NOT TARGET AWS::crypto AND 112 | (EXISTS "${crypto_LIBRARY}") 113 | ) 114 | set(THREADS_PREFER_PTHREAD_FLAG ON) 115 | find_package(Threads REQUIRED) 116 | add_library(AWS::crypto UNKNOWN IMPORTED) 117 | set_target_properties(AWS::crypto PROPERTIES 118 | INTERFACE_INCLUDE_DIRECTORIES "${crypto_INCLUDE_DIR}") 119 | set_target_properties(AWS::crypto PROPERTIES 120 | IMPORTED_LINK_INTERFACE_LANGUAGES "C" 121 | IMPORTED_LOCATION "${crypto_LIBRARY}") 122 | add_dependencies(AWS::crypto Threads::Threads) 123 | endif() 124 | endif() 125 | 126 | endif() 127 | -------------------------------------------------------------------------------- /cmake/modules/aws-lc.cmake: -------------------------------------------------------------------------------- 1 | # This can be used by downstream consumers (most likely CRT libraries) 2 | # to build and embed aws-lc as libcrypto into the final library/binary 3 | # This will create a crypto lib that is findable via find_package(LibCrypto) 4 | # and is compatible with s2n and aws-c-cal 5 | 6 | file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/aws-lc) 7 | execute_process( 8 | COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} 9 | -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} 10 | -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} 11 | -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} 12 | -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} 13 | -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} 14 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 15 | -DBUILD_TESTING=OFF 16 | -DBUILD_LIBSSL=OFF 17 | -DDISABLE_GO=ON # disables codegen 18 | -DDISABLE_PERL=ON # disables codegen 19 | -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} 20 | ${CMAKE_CURRENT_SOURCE_DIR}/crt/aws-lc 21 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/aws-lc 22 | RESULT_VARIABLE BUILD_AWSLC_EXIT_CODE 23 | ) 24 | if (NOT ${BUILD_AWSLC_EXIT_CODE} EQUAL 0) 25 | message(FATAL_ERROR "Failed to configure aws-lc") 26 | endif() 27 | execute_process( 28 | COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/aws-lc --config ${CMAKE_BUILD_TYPE} --target install 29 | RESULT_VARIABLE BUILD_AWSLC_EXIT_CODE 30 | ) 31 | if (NOT ${BUILD_AWSLC_EXIT_CODE} EQUAL 0) 32 | message(FATAL_ERROR "Failed to build aws-lc") 33 | endif() 34 | list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/aws-lc") 35 | -------------------------------------------------------------------------------- /format-check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import os 4 | from pathlib import Path 5 | import re 6 | from subprocess import list2cmdline, run 7 | from tempfile import NamedTemporaryFile 8 | 9 | CLANG_FORMAT_VERSION = '18.1.6' 10 | 11 | INCLUDE_REGEX = re.compile( 12 | r'^(include|source|tests|verification)/.*\.(c|h|inl)$') 13 | EXCLUDE_REGEX = re.compile(r'^$') 14 | 15 | arg_parser = argparse.ArgumentParser(description="Check with clang-format") 16 | arg_parser.add_argument('-i', '--inplace-edit', action='store_true', 17 | help="Edit files inplace") 18 | args = arg_parser.parse_args() 19 | 20 | os.chdir(Path(__file__).parent) 21 | 22 | # create file containing list of all files to format 23 | filepaths_file = NamedTemporaryFile(delete=False) 24 | for dirpath, dirnames, filenames in os.walk('.'): 25 | for filename in filenames: 26 | # our regexes expect filepath to use forward slash 27 | filepath = Path(dirpath, filename).as_posix() 28 | if not INCLUDE_REGEX.match(filepath): 29 | continue 30 | if EXCLUDE_REGEX.match(filepath): 31 | continue 32 | 33 | filepaths_file.write(f"{filepath}\n".encode()) 34 | filepaths_file.close() 35 | 36 | # use pipx to run clang-format from PyPI 37 | # this is a simple way to run the same clang-format version regardless of OS 38 | cmd = ['pipx', 'run', f'clang-format=={CLANG_FORMAT_VERSION}', 39 | f'--files={filepaths_file.name}'] 40 | if args.inplace_edit: 41 | cmd += ['-i'] 42 | else: 43 | cmd += ['--Werror', '--dry-run'] 44 | 45 | print(f"{Path.cwd()}$ {list2cmdline(cmd)}") 46 | if run(cmd).returncode: 47 | exit(1) 48 | -------------------------------------------------------------------------------- /include/aws/cal/cal.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_CAL_H 2 | #define AWS_CAL_CAL_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | AWS_PUSH_SANE_WARNING_LEVEL 14 | 15 | struct aws_allocator; 16 | 17 | #define AWS_C_CAL_PACKAGE_ID 7 18 | 19 | enum aws_cal_errors { 20 | AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED = AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_CAL_PACKAGE_ID), 21 | AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT, 22 | AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM, 23 | AWS_ERROR_CAL_UNKNOWN_OBJECT_IDENTIFIER, 24 | AWS_ERROR_CAL_MALFORMED_ASN1_ENCOUNTERED, 25 | AWS_ERROR_CAL_MISMATCHED_DER_TYPE, 26 | AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM, 27 | AWS_ERROR_CAL_BUFFER_TOO_LARGE_FOR_ALGORITHM, 28 | AWS_ERROR_CAL_INVALID_CIPHER_MATERIAL_SIZE_FOR_ALGORITHM, 29 | AWS_ERROR_CAL_DER_UNSUPPORTED_NEGATIVE_INT, 30 | AWS_ERROR_CAL_UNSUPPORTED_KEY_FORMAT, 31 | AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED, 32 | AWS_ERROR_CAL_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_CAL_PACKAGE_ID) 33 | }; 34 | 35 | enum aws_cal_log_subject { 36 | AWS_LS_CAL_GENERAL = AWS_LOG_SUBJECT_BEGIN_RANGE(AWS_C_CAL_PACKAGE_ID), 37 | AWS_LS_CAL_ECC, 38 | AWS_LS_CAL_HASH, 39 | AWS_LS_CAL_HMAC, 40 | AWS_LS_CAL_DER, 41 | AWS_LS_CAL_LIBCRYPTO_RESOLVE, 42 | AWS_LS_CAL_RSA, 43 | AWS_LS_CAL_ED25519, 44 | 45 | AWS_LS_CAL_LAST = AWS_LOG_SUBJECT_END_RANGE(AWS_C_CAL_PACKAGE_ID) 46 | }; 47 | 48 | AWS_EXTERN_C_BEGIN 49 | 50 | AWS_CAL_API void aws_cal_library_init(struct aws_allocator *allocator); 51 | AWS_CAL_API void aws_cal_library_clean_up(void); 52 | 53 | /* 54 | * Every CRT thread that might invoke aws-lc functionality should call this as part of the thread at_exit process 55 | */ 56 | AWS_CAL_API void aws_cal_thread_clean_up(void); 57 | 58 | AWS_EXTERN_C_END 59 | AWS_POP_SANE_WARNING_LEVEL 60 | 61 | #endif /* AWS_CAL_CAL_H */ 62 | -------------------------------------------------------------------------------- /include/aws/cal/ecc.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_ECC_H 2 | #define AWS_CAL_ECC_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | AWS_PUSH_SANE_WARNING_LEVEL 14 | 15 | enum aws_ecc_curve_name { 16 | AWS_CAL_ECDSA_P256, 17 | AWS_CAL_ECDSA_P384, 18 | }; 19 | 20 | struct aws_ecc_key_pair; 21 | 22 | typedef void aws_ecc_key_pair_destroy_fn(struct aws_ecc_key_pair *key_pair); 23 | typedef int aws_ecc_key_pair_sign_message_fn( 24 | const struct aws_ecc_key_pair *key_pair, 25 | const struct aws_byte_cursor *message, 26 | struct aws_byte_buf *signature_output); 27 | typedef int aws_ecc_key_pair_derive_public_key_fn(struct aws_ecc_key_pair *key_pair); 28 | typedef int aws_ecc_key_pair_verify_signature_fn( 29 | const struct aws_ecc_key_pair *signer, 30 | const struct aws_byte_cursor *message, 31 | const struct aws_byte_cursor *signature); 32 | typedef size_t aws_ecc_key_pair_signature_length_fn(const struct aws_ecc_key_pair *signer); 33 | 34 | struct aws_ecc_key_pair_vtable { 35 | aws_ecc_key_pair_destroy_fn *destroy; 36 | aws_ecc_key_pair_derive_public_key_fn *derive_pub_key; 37 | aws_ecc_key_pair_sign_message_fn *sign_message; 38 | aws_ecc_key_pair_verify_signature_fn *verify_signature; 39 | aws_ecc_key_pair_signature_length_fn *signature_length; 40 | }; 41 | 42 | struct aws_ecc_key_pair { 43 | struct aws_allocator *allocator; 44 | struct aws_atomic_var ref_count; 45 | enum aws_ecc_curve_name curve_name; 46 | struct aws_byte_buf key_buf; 47 | struct aws_byte_buf pub_x; 48 | struct aws_byte_buf pub_y; 49 | struct aws_byte_buf priv_d; 50 | struct aws_ecc_key_pair_vtable *vtable; 51 | void *impl; 52 | }; 53 | 54 | AWS_EXTERN_C_BEGIN 55 | 56 | /** 57 | * Adds one to an ecc key pair's ref count. 58 | */ 59 | AWS_CAL_API void aws_ecc_key_pair_acquire(struct aws_ecc_key_pair *key_pair); 60 | 61 | /** 62 | * Subtracts one from an ecc key pair's ref count. If ref count reaches zero, the key pair is destroyed. 63 | */ 64 | AWS_CAL_API void aws_ecc_key_pair_release(struct aws_ecc_key_pair *key_pair); 65 | 66 | /** 67 | * Creates an Elliptic Curve private key that can be used for signing. 68 | * Returns a new instance of aws_ecc_key_pair if the key was successfully built. 69 | * Otherwise returns NULL. Note: priv_key::len must match the appropriate length 70 | * for the selected curve_name. 71 | */ 72 | AWS_CAL_API struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key( 73 | struct aws_allocator *allocator, 74 | enum aws_ecc_curve_name curve_name, 75 | const struct aws_byte_cursor *priv_key); 76 | 77 | #if !defined(AWS_OS_IOS) 78 | /** 79 | * Creates an Elliptic Curve public/private key pair that can be used for signing and verifying. 80 | * Returns a new instance of aws_ecc_key_pair if the key was successfully built. 81 | * Otherwise returns NULL. 82 | * Note: On Apple platforms this function is only supported on MacOS. This is 83 | * due to usage of SecItemExport, which is only available on MacOS 10.7+ 84 | * (yes, MacOS only and no other Apple platforms). There are alternatives for 85 | * ios and other platforms, but they are ugly to use. Hence for now it only 86 | * supports this call on MacOS. 87 | */ 88 | AWS_CAL_API struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random( 89 | struct aws_allocator *allocator, 90 | enum aws_ecc_curve_name curve_name); 91 | #endif /* !AWS_OS_IOS */ 92 | 93 | /** 94 | * Creates an Elliptic Curve public key that can be used for verifying. 95 | * Returns a new instance of aws_ecc_key_pair if the key was successfully built. 96 | * Otherwise returns NULL. Note: public_key_x::len and public_key_y::len must 97 | * match the appropriate length for the selected curve_name. 98 | */ 99 | AWS_CAL_API struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key( 100 | struct aws_allocator *allocator, 101 | enum aws_ecc_curve_name curve_name, 102 | const struct aws_byte_cursor *public_key_x, 103 | const struct aws_byte_cursor *public_key_y); 104 | 105 | /** 106 | * Creates an Elliptic Curve public/private key pair from a DER encoded key pair. 107 | * Returns a new instance of aws_ecc_key_pair if the key was successfully built. 108 | * Otherwise returns NULL. Whether or not signing or verification can be perform depends 109 | * on if encoded_keys is a public/private pair or a public key. 110 | */ 111 | AWS_CAL_API struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1( 112 | struct aws_allocator *allocator, 113 | const struct aws_byte_cursor *encoded_keys); 114 | 115 | /** 116 | * Creates an Elliptic curve public key from x and y coordinates encoded as hex strings 117 | * Returns a new instance of aws_ecc_key_pair if the key was successfully built. 118 | * Otherwise returns NULL. 119 | */ 120 | AWS_CAL_API struct aws_ecc_key_pair *aws_ecc_key_new_from_hex_coordinates( 121 | struct aws_allocator *allocator, 122 | enum aws_ecc_curve_name curve_name, 123 | struct aws_byte_cursor pub_x_hex_cursor, 124 | struct aws_byte_cursor pub_y_hex_cursor); 125 | 126 | /** 127 | * Derives a public key from the private key if supported by this operating system (not supported on OSX). 128 | * key_pair::pub_x and key_pair::pub_y will be set with the raw key buffers. 129 | */ 130 | AWS_CAL_API int aws_ecc_key_pair_derive_public_key(struct aws_ecc_key_pair *key_pair); 131 | 132 | /** 133 | * Get the curve name from the oid. OID here is the payload of the DER encoded ASN.1 part (doesn't include 134 | * type specifier or length. On success, the value of curve_name will be set. 135 | */ 136 | AWS_CAL_API int aws_ecc_curve_name_from_oid(struct aws_byte_cursor *oid, enum aws_ecc_curve_name *curve_name); 137 | 138 | /** 139 | * Get the DER encoded OID from the curve_name. The OID in this case will not contain the type or the length specifier. 140 | */ 141 | AWS_CAL_API int aws_ecc_oid_from_curve_name(enum aws_ecc_curve_name curve_name, struct aws_byte_cursor *oid); 142 | 143 | /** 144 | * Uses the key_pair's private key to sign message. The output will be in signature. Signature must be large enough 145 | * to hold the signature. Check aws_ecc_key_pair_signature_length() for the appropriate size. Signature will be DER 146 | * encoded. 147 | * 148 | * It is the callers job to make sure message is the appropriate cryptographic digest for this operation. It's usually 149 | * something like a SHA256. 150 | */ 151 | AWS_CAL_API int aws_ecc_key_pair_sign_message( 152 | const struct aws_ecc_key_pair *key_pair, 153 | const struct aws_byte_cursor *message, 154 | struct aws_byte_buf *signature); 155 | 156 | /** 157 | * Uses the key_pair's public key to verify signature of message. Signature should be DER 158 | * encoded. 159 | * 160 | * It is the callers job to make sure message is the appropriate cryptographic digest for this operation. It's usually 161 | * something like a SHA256. 162 | * 163 | * returns AWS_OP_SUCCESS if the signature is valid. 164 | */ 165 | AWS_CAL_API int aws_ecc_key_pair_verify_signature( 166 | const struct aws_ecc_key_pair *key_pair, 167 | const struct aws_byte_cursor *message, 168 | const struct aws_byte_cursor *signature); 169 | AWS_CAL_API size_t aws_ecc_key_pair_signature_length(const struct aws_ecc_key_pair *key_pair); 170 | 171 | AWS_CAL_API void aws_ecc_key_pair_get_public_key( 172 | const struct aws_ecc_key_pair *key_pair, 173 | struct aws_byte_cursor *pub_x, 174 | struct aws_byte_cursor *pub_y); 175 | 176 | AWS_CAL_API void aws_ecc_key_pair_get_private_key( 177 | const struct aws_ecc_key_pair *key_pair, 178 | struct aws_byte_cursor *private_d); 179 | 180 | AWS_CAL_API size_t aws_ecc_key_coordinate_byte_size_from_curve_name(enum aws_ecc_curve_name curve_name); 181 | 182 | AWS_EXTERN_C_END 183 | AWS_POP_SANE_WARNING_LEVEL 184 | 185 | #endif /* AWS_CAL_ECC_H */ 186 | -------------------------------------------------------------------------------- /include/aws/cal/ed25519.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_ED25519_H 2 | #define AWS_CAL_ED25519_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | #include 9 | 10 | AWS_PUSH_SANE_WARNING_LEVEL 11 | 12 | struct aws_ed25519_key_pair; 13 | 14 | AWS_EXTERN_C_BEGIN 15 | 16 | /** 17 | * Generate new Ed25519 key. 18 | * Returns a new instance of aws_ed25519_key_pair if the key was successfully generated. 19 | * Otherwise returns NULL. 20 | * Note: keygen is not supported on all platforms and will return NULL for the key 21 | * and raise AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM. 22 | * Examples of unsupported cases: 23 | * - openssl pre 1.1.1 (Note: aws-lc and boringssl both expose the needed functions) 24 | * - win/mac builds without special flag that forces linking to libcrypto to support this 25 | */ 26 | AWS_CAL_API struct aws_ed25519_key_pair *aws_ed25519_key_pair_new_generate(struct aws_allocator *allocator); 27 | 28 | /** 29 | * Adds one to an Ed25519 key pair's ref count. 30 | * Returns key_pair pointer. 31 | */ 32 | AWS_CAL_API struct aws_ed25519_key_pair *aws_ed25519_key_pair_acquire(struct aws_ed25519_key_pair *key_pair); 33 | 34 | /** 35 | * Subtracts one from an Ed25519 key pair's ref count. If ref count reaches zero, the key pair is destroyed. 36 | * Always returns NULL. 37 | */ 38 | AWS_CAL_API struct aws_ed25519_key_pair *aws_ed25519_key_pair_release(struct aws_ed25519_key_pair *key_pair); 39 | 40 | enum aws_ed25519_key_export_format { 41 | /* Export the key as raw bytes */ 42 | AWS_CAL_ED25519_KEY_EXPORT_RAW, 43 | 44 | /** 45 | * Export the key to openssh format. 46 | * This will only export the key block, framing (i.e. pem) is left as exercise for the caller. 47 | * b64 encoding is done as convenience since common framing formats require it. 48 | */ 49 | AWS_CAL_ED25519_KEY_EXPORT_OPENSSH_B64, 50 | }; 51 | 52 | /* 53 | * Get public key for the key pair. 54 | * Key in specified format is appended to the buffer. 55 | * The buffer must be initialized before this call, with sufficient capacity to hold the result. 56 | * Use aws_ed25519_key_pair_get_public_key_size to figure out how much capacity buffer needs for a given format. 57 | */ 58 | AWS_CAL_API int aws_ed25519_key_pair_get_public_key( 59 | const struct aws_ed25519_key_pair *key_pair, 60 | enum aws_ed25519_key_export_format format, 61 | struct aws_byte_buf *out); 62 | 63 | /** 64 | * Gets the size of the exported public key. 65 | */ 66 | AWS_CAL_API size_t aws_ed25519_key_pair_get_public_key_size(enum aws_ed25519_key_export_format format); 67 | 68 | /* 69 | * Get private key for the key pair. 70 | * Key in specified format is appended to the buffer. 71 | * The buffer must be initialized before this call, with sufficient capacity to hold the result. 72 | * Use aws_ed25519_key_pair_get_private_key_size to figure out how much capacity buffer needs for a given format. 73 | */ 74 | AWS_CAL_API int aws_ed25519_key_pair_get_private_key( 75 | const struct aws_ed25519_key_pair *key_pair, 76 | enum aws_ed25519_key_export_format format, 77 | struct aws_byte_buf *out); 78 | 79 | /** 80 | * Gets the size of the exported private key. 81 | */ 82 | AWS_CAL_API size_t aws_ed25519_key_pair_get_private_key_size(enum aws_ed25519_key_export_format format); 83 | 84 | AWS_EXTERN_C_END 85 | 86 | AWS_POP_SANE_WARNING_LEVEL 87 | 88 | #endif /* AWS_CAL_ED25519_H */ 89 | -------------------------------------------------------------------------------- /include/aws/cal/exports.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_EXPORTS_H 2 | #define AWS_CAL_EXPORTS_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #if defined(AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined(_WIN32) 8 | # ifdef AWS_CAL_USE_IMPORT_EXPORT 9 | # ifdef AWS_CAL_EXPORTS 10 | # define AWS_CAL_API __declspec(dllexport) 11 | # else 12 | # define AWS_CAL_API __declspec(dllimport) 13 | # endif /* AWS_CAL_EXPORTS */ 14 | # else 15 | # define AWS_CAL_API 16 | # endif /* AWS_CAL_USE_IMPORT_EXPORT */ 17 | 18 | #else /* defined (AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) */ 19 | 20 | # if defined(AWS_CAL_USE_IMPORT_EXPORT) && defined(AWS_CAL_EXPORTS) 21 | # define AWS_CAL_API __attribute__((visibility("default"))) 22 | # else 23 | # define AWS_CAL_API 24 | # endif 25 | 26 | #endif /* defined (AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) */ 27 | 28 | #endif /* AWS_CAL_EXPORTS_H */ 29 | -------------------------------------------------------------------------------- /include/aws/cal/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_HASH_H_ 2 | #define AWS_CAL_HASH_H_ 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | AWS_PUSH_SANE_WARNING_LEVEL 13 | 14 | #define AWS_SHA256_LEN 32 15 | #define AWS_SHA1_LEN 20 16 | #define AWS_MD5_LEN 16 17 | 18 | struct aws_hash; 19 | 20 | struct aws_hash_vtable { 21 | const char *alg_name; 22 | const char *provider; 23 | void (*destroy)(struct aws_hash *hash); 24 | int (*update)(struct aws_hash *hash, const struct aws_byte_cursor *buf); 25 | int (*finalize)(struct aws_hash *hash, struct aws_byte_buf *out); 26 | }; 27 | 28 | struct aws_hash { 29 | struct aws_allocator *allocator; 30 | struct aws_hash_vtable *vtable; 31 | size_t digest_size; 32 | bool good; 33 | void *impl; 34 | }; 35 | 36 | typedef struct aws_hash *(aws_hash_new_fn)(struct aws_allocator *allocator); 37 | 38 | AWS_EXTERN_C_BEGIN 39 | /** 40 | * Allocates and initializes a sha256 hash instance. 41 | */ 42 | AWS_CAL_API struct aws_hash *aws_sha256_new(struct aws_allocator *allocator); 43 | /** 44 | * Allocates and initializes a sha1 hash instance. 45 | */ 46 | AWS_CAL_API struct aws_hash *aws_sha1_new(struct aws_allocator *allocator); 47 | /** 48 | * Allocates and initializes an md5 hash instance. 49 | */ 50 | AWS_CAL_API struct aws_hash *aws_md5_new(struct aws_allocator *allocator); 51 | 52 | /** 53 | * Cleans up and deallocates hash. 54 | */ 55 | AWS_CAL_API void aws_hash_destroy(struct aws_hash *hash); 56 | /** 57 | * Updates the running hash with to_hash. this can be called multiple times. 58 | */ 59 | AWS_CAL_API int aws_hash_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); 60 | /** 61 | * Completes the hash computation and writes the final digest to output. 62 | * Allocation of output is the caller's responsibility. If you specify 63 | * truncate_to to something other than 0, the output will be truncated to that 64 | * number of bytes. For example, if you want a SHA256 digest as the first 16 65 | * bytes, set truncate_to to 16. If you want the full digest size, just set this 66 | * to 0. 67 | */ 68 | AWS_CAL_API int aws_hash_finalize(struct aws_hash *hash, struct aws_byte_buf *output, size_t truncate_to); 69 | 70 | /** 71 | * Computes the md5 hash over input and writes the digest output to 'output'. 72 | * Use this if you don't need to stream the data you're hashing and you can load 73 | * the entire input to hash into memory. 74 | */ 75 | AWS_CAL_API int aws_md5_compute( 76 | struct aws_allocator *allocator, 77 | const struct aws_byte_cursor *input, 78 | struct aws_byte_buf *output, 79 | size_t truncate_to); 80 | 81 | /** 82 | * Computes the sha256 hash over input and writes the digest output to 'output'. 83 | * Use this if you don't need to stream the data you're hashing and you can load 84 | * the entire input to hash into memory. If you specify truncate_to to something 85 | * other than 0, the output will be truncated to that number of bytes. For 86 | * example, if you want a SHA256 digest as the first 16 bytes, set truncate_to 87 | * to 16. If you want the full digest size, just set this to 0. 88 | */ 89 | AWS_CAL_API int aws_sha256_compute( 90 | struct aws_allocator *allocator, 91 | const struct aws_byte_cursor *input, 92 | struct aws_byte_buf *output, 93 | size_t truncate_to); 94 | 95 | /** 96 | * Computes the sha1 hash over input and writes the digest output to 'output'. 97 | * Use this if you don't need to stream the data you're hashing and you can load 98 | * the entire input to hash into memory. If you specify truncate_to to something 99 | * other than 0, the output will be truncated to that number of bytes. For 100 | * example, if you want a SHA1 digest as the first 16 bytes, set truncate_to 101 | * to 16. If you want the full digest size, just set this to 0. 102 | */ 103 | AWS_CAL_API int aws_sha1_compute( 104 | struct aws_allocator *allocator, 105 | const struct aws_byte_cursor *input, 106 | struct aws_byte_buf *output, 107 | size_t truncate_to); 108 | 109 | /** 110 | * Set the implementation of md5 to use. If you compiled without BYO_CRYPTO, 111 | * you do not need to call this. However, if use this, we will honor it, 112 | * regardless of compile options. This may be useful for testing purposes. If 113 | * you did set BYO_CRYPTO, and you do not call this function you will 114 | * segfault. 115 | */ 116 | AWS_CAL_API void aws_set_md5_new_fn(aws_hash_new_fn *fn); 117 | 118 | /** 119 | * Set the implementation of sha256 to use. If you compiled without 120 | * BYO_CRYPTO, you do not need to call this. However, if use this, we will 121 | * honor it, regardless of compile options. This may be useful for testing 122 | * purposes. If you did set BYO_CRYPTO, and you do not call this function 123 | * you will segfault. 124 | */ 125 | AWS_CAL_API void aws_set_sha256_new_fn(aws_hash_new_fn *fn); 126 | 127 | /** 128 | * Set the implementation of sha1 to use. If you compiled without 129 | * BYO_CRYPTO, you do not need to call this. However, if use this, we will 130 | * honor it, regardless of compile options. This may be useful for testing 131 | * purposes. If you did set BYO_CRYPTO, and you do not call this function 132 | * you will segfault. 133 | */ 134 | AWS_CAL_API void aws_set_sha1_new_fn(aws_hash_new_fn *fn); 135 | 136 | AWS_EXTERN_C_END 137 | AWS_POP_SANE_WARNING_LEVEL 138 | 139 | #endif /* AWS_CAL_HASH_H_ */ 140 | -------------------------------------------------------------------------------- /include/aws/cal/hmac.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_HMAC_H_ 2 | #define AWS_CAL_HMAC_H_ 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | AWS_PUSH_SANE_WARNING_LEVEL 13 | 14 | #define AWS_SHA256_HMAC_LEN 32 15 | 16 | struct aws_hmac; 17 | 18 | struct aws_hmac_vtable { 19 | const char *alg_name; 20 | const char *provider; 21 | void (*destroy)(struct aws_hmac *hmac); 22 | int (*update)(struct aws_hmac *hmac, const struct aws_byte_cursor *buf); 23 | int (*finalize)(struct aws_hmac *hmac, struct aws_byte_buf *out); 24 | }; 25 | 26 | struct aws_hmac { 27 | struct aws_allocator *allocator; 28 | struct aws_hmac_vtable *vtable; 29 | size_t digest_size; 30 | bool good; 31 | void *impl; 32 | }; 33 | 34 | typedef struct aws_hmac *(aws_hmac_new_fn)(struct aws_allocator *allocator, const struct aws_byte_cursor *secret); 35 | 36 | AWS_EXTERN_C_BEGIN 37 | /** 38 | * Allocates and initializes a sha256 hmac instance. Secret is the key to be 39 | * used for the hmac process. 40 | */ 41 | AWS_CAL_API struct aws_hmac *aws_sha256_hmac_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret); 42 | 43 | /** 44 | * Cleans up and deallocates hmac. 45 | */ 46 | AWS_CAL_API void aws_hmac_destroy(struct aws_hmac *hmac); 47 | 48 | /** 49 | * Updates the running hmac with to_hash. this can be called multiple times. 50 | */ 51 | AWS_CAL_API int aws_hmac_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac); 52 | /** 53 | * Completes the hmac computation and writes the final digest to output. 54 | * Allocation of output is the caller's responsibility. If you specify 55 | * truncate_to to something other than 0, the output will be truncated to that 56 | * number of bytes. For example if you want a SHA256 digest as the first 16 57 | * bytes, set truncate_to to 16. If you want the full digest size, just set this 58 | * to 0. 59 | */ 60 | AWS_CAL_API int aws_hmac_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output, size_t truncate_to); 61 | /** 62 | * Computes the sha256 hmac over input and writes the digest output to 'output'. 63 | * Use this if you don't need to stream the data you're hashing and you can load 64 | * the entire input to hash into memory. If you specify truncate_to to something 65 | * other than 0, the output will be truncated to that number of bytes. For 66 | * example if you want a SHA256 HMAC digest as the first 16 bytes, set 67 | * truncate_to to 16. If you want the full digest size, just set this to 0. 68 | */ 69 | AWS_CAL_API int aws_sha256_hmac_compute( 70 | struct aws_allocator *allocator, 71 | const struct aws_byte_cursor *secret, 72 | const struct aws_byte_cursor *to_hmac, 73 | struct aws_byte_buf *output, 74 | size_t truncate_to); 75 | /** 76 | * Set the implementation of sha256 hmac to use. If you compiled without 77 | * BYO_CRYPTO, you do not need to call this. However, if use this, we will 78 | * honor it, regardless of compile options. This may be useful for testing 79 | * purposes. If you did set BYO_CRYPTO, and you do not call this function 80 | * you will segfault. 81 | */ 82 | AWS_CAL_API void aws_set_sha256_hmac_new_fn(aws_hmac_new_fn *fn); 83 | 84 | AWS_EXTERN_C_END 85 | AWS_POP_SANE_WARNING_LEVEL 86 | 87 | #endif /* AWS_CAL_HASH_H_ */ 88 | -------------------------------------------------------------------------------- /include/aws/cal/private/der.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_C_CAL_DER_H 2 | #define AWS_C_CAL_DER_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | struct aws_der_encoder; 14 | struct aws_der_decoder; 15 | 16 | /* 17 | * Note: encoder/decoder only supports unsigned representations of integers and usage 18 | * of signed integers might lead to unexpected results. 19 | * Context: DER spec requires ints to be stored in big endian format with MSB 20 | * representing signedness. To disambiguate between negative number and big 21 | * positive number, null byte can be added in front of positive number. DER spec 22 | * requires representation to be the shortest possible one. 23 | * During encoding aws_der_encoder_write_unsigned_integer assumes that cursor 24 | * points to a positive number and will prepend 0 if needed by DER spec to 25 | * indicate its positive number. Encoder does not support writing negative numbers. 26 | * Decoder aws_der_encoder_write_unsigned_integer will strip any leading 0 as 27 | * needed and will error out if der contains negative number. 28 | * Take special care when integrating with 3p libraries cause they might expect 29 | * different format. Ex. this format matches what openssl calls bin format 30 | * (BN_bin2bn) and might not work as expected with openssl mpi format. 31 | */ 32 | 33 | enum aws_der_type { 34 | /* Primitives */ 35 | AWS_DER_BOOLEAN = 0x01, 36 | AWS_DER_INTEGER = 0x02, 37 | AWS_DER_BIT_STRING = 0x03, 38 | AWS_DER_OCTET_STRING = 0x04, 39 | AWS_DER_NULL = 0x05, 40 | AWS_DER_OBJECT_IDENTIFIER = 0x06, 41 | AWS_DER_BMPString = 0x1e, 42 | AWS_DER_UNICODE_STRING = AWS_DER_BMPString, 43 | AWS_DER_IA5String = 0x16, /* Unsupported */ 44 | AWS_DER_PrintableString = 0x13, 45 | AWS_DER_TeletexString = 0x14, /* Unsupported */ 46 | 47 | /* Constructed types */ 48 | AWS_DER_SEQUENCE = 0x30, 49 | AWS_DER_SEQUENCE_OF = AWS_DER_SEQUENCE, 50 | AWS_DER_SET = 0x31, 51 | AWS_DER_SET_OF = AWS_DER_SET, 52 | AWS_DER_UTF8_STRING = 0x0c, 53 | 54 | /* class types */ 55 | AWS_DER_CLASS_UNIVERSAL = 0x00, 56 | AWS_DER_CLASS_APPLICATION = 0x40, 57 | AWS_DER_CLASS_CONTEXT = 0x80, 58 | AWS_DER_CLASS_PRIVATE = 0xc0, 59 | 60 | /* forms */ 61 | AWS_DER_FORM_CONSTRUCTED = 0x20, 62 | AWS_DER_FORM_PRIMITIVE = 0x00, 63 | }; 64 | 65 | AWS_EXTERN_C_BEGIN 66 | 67 | /** 68 | * Initializes a DER encoder 69 | * @param allocator The allocator to use for all allocations within the encoder 70 | * @param capacity The initial capacity of the encoder scratch buffer (the max size of all encoded TLVs) 71 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 72 | */ 73 | AWS_CAL_API struct aws_der_encoder *aws_der_encoder_new(struct aws_allocator *allocator, size_t capacity); 74 | 75 | /** 76 | * Cleans up a DER encoder 77 | * @param encoder The encoder to clean up 78 | * 79 | * Note that this destroys the encoder buffer, invalidating any references to the contents given via get_contents() 80 | */ 81 | AWS_CAL_API void aws_der_encoder_destroy(struct aws_der_encoder *encoder); 82 | 83 | /** 84 | * Writes an arbitrarily sized integer to the DER stream 85 | * @param encoder The encoder to use 86 | * @param integer A cursor pointing to the integer's memory 87 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 88 | */ 89 | AWS_CAL_API int aws_der_encoder_write_unsigned_integer(struct aws_der_encoder *encoder, struct aws_byte_cursor integer); 90 | /** 91 | * Writes a boolean to the DER stream 92 | * @param encoder The encoder to use 93 | * @param boolean The boolean to write 94 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 95 | */ 96 | AWS_CAL_API int aws_der_encoder_write_boolean(struct aws_der_encoder *encoder, bool boolean); 97 | 98 | /** 99 | * Writes a NULL token to the stream 100 | * @param encoder The encoder to write to 101 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 102 | */ 103 | AWS_CAL_API int aws_der_encoder_write_null(struct aws_der_encoder *encoder); 104 | 105 | /** 106 | * Writes a BIT_STRING to the stream 107 | * @param encoder The encoder to use 108 | * @param bit_string The bit string to encode 109 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 110 | */ 111 | AWS_CAL_API int aws_der_encoder_write_bit_string(struct aws_der_encoder *encoder, struct aws_byte_cursor bit_string); 112 | 113 | /** 114 | * Writes a string to the stream 115 | * @param encoder The encoder to use 116 | * @param octet_string The string to encode 117 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 118 | */ 119 | AWS_CAL_API int aws_der_encoder_write_octet_string( 120 | struct aws_der_encoder *encoder, 121 | struct aws_byte_cursor octet_string); 122 | 123 | /** 124 | * Begins a SEQUENCE of objects in the DER stream 125 | * @param encoder The encoder to use 126 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 127 | */ 128 | AWS_CAL_API int aws_der_encoder_begin_sequence(struct aws_der_encoder *encoder); 129 | 130 | /** 131 | * Finishes a SEQUENCE and applies it to the DER stream buffer 132 | * @param encoder The encoder to update 133 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 134 | */ 135 | AWS_CAL_API int aws_der_encoder_end_sequence(struct aws_der_encoder *encoder); 136 | 137 | /** 138 | * Begins a SET of objects in the DER stream 139 | * @param encoder The encoder to use 140 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 141 | */ 142 | AWS_CAL_API int aws_der_encoder_begin_set(struct aws_der_encoder *encoder); 143 | 144 | /** 145 | * Finishes a SET and applies it to the DER stream buffer 146 | * @param encoder The encoder to update 147 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 148 | */ 149 | AWS_CAL_API int aws_der_encoder_end_set(struct aws_der_encoder *encoder); 150 | 151 | /** 152 | * Retrieves the contents of the encoder stream buffer 153 | * @param encoder The encoder to read from 154 | * @param cursor The cursor to point at the stream buffer 155 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 156 | */ 157 | AWS_CAL_API int aws_der_encoder_get_contents(struct aws_der_encoder *encoder, struct aws_byte_cursor *contents); 158 | 159 | /** 160 | * Initializes an DER decoder 161 | * @param allocator The allocator to use 162 | * @param input The DER formatted buffer to parse 163 | * @return Initialized decoder, or NULL 164 | */ 165 | AWS_CAL_API struct aws_der_decoder *aws_der_decoder_new(struct aws_allocator *allocator, struct aws_byte_cursor input); 166 | 167 | /** 168 | * Cleans up a DER encoder 169 | * @param decoder The encoder to clean up 170 | */ 171 | AWS_CAL_API void aws_der_decoder_destroy(struct aws_der_decoder *decoder); 172 | 173 | /** 174 | * Allows for iteration over the decoded TLVs. 175 | * @param decoder The decoder to iterate over 176 | * @return true if there is a tlv to read after advancing, false when done 177 | */ 178 | AWS_CAL_API bool aws_der_decoder_next(struct aws_der_decoder *decoder); 179 | 180 | /** 181 | * The type of the current TLV 182 | * @param decoder The decoder to inspect 183 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 184 | */ 185 | AWS_CAL_API enum aws_der_type aws_der_decoder_tlv_type(struct aws_der_decoder *decoder); 186 | 187 | /** 188 | * The size of the current TLV 189 | * @param decoder The decoder to inspect 190 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 191 | */ 192 | AWS_CAL_API size_t aws_der_decoder_tlv_length(struct aws_der_decoder *decoder); 193 | 194 | /** 195 | * The number of elements in the current TLV container 196 | * @param decoder The decoder to inspect 197 | * @return Number of elements in the current container 198 | */ 199 | AWS_CAL_API size_t aws_der_decoder_tlv_count(struct aws_der_decoder *decoder); 200 | 201 | /** 202 | * Extracts the current TLV string value (BIT_STRING, OCTET_STRING) 203 | * @param decoder The decoder to extract from 204 | * @param string The buffer to store the string into 205 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 206 | */ 207 | AWS_CAL_API int aws_der_decoder_tlv_string(struct aws_der_decoder *decoder, struct aws_byte_cursor *string); 208 | 209 | /** 210 | * Extracts the current TLV INTEGER value (INTEGER) 211 | * @param decoder The decoder to extract from 212 | * @param integer The buffer to store the integer into 213 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 214 | */ 215 | AWS_CAL_API int aws_der_decoder_tlv_unsigned_integer(struct aws_der_decoder *decoder, struct aws_byte_cursor *integer); 216 | 217 | /** 218 | * Extracts the current TLV BOOLEAN value (BOOLEAN) 219 | * @param decoder The decoder to extract from 220 | * @param boolean The boolean to store the value into 221 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 222 | */ 223 | AWS_CAL_API int aws_der_decoder_tlv_boolean(struct aws_der_decoder *decoder, bool *boolean); 224 | 225 | /** 226 | * Extracts the current TLV value as a blob 227 | * @param decoder The decoder to extract from 228 | * @param blob The buffer to store the value into 229 | * @return AWS_OP_ERR if an error occurs, otherwise AWS_OP_SUCCESS 230 | */ 231 | AWS_CAL_API int aws_der_decoder_tlv_blob(struct aws_der_decoder *decoder, struct aws_byte_cursor *blob); 232 | 233 | AWS_EXTERN_C_END 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /include/aws/cal/private/ecc.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_C_CAL_PRIVATE_ECC_H 2 | #define AWS_C_CAL_PRIVATE_ECC_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | struct aws_der_decoder; 13 | 14 | AWS_EXTERN_C_BEGIN 15 | 16 | AWS_CAL_API int aws_der_decoder_load_ecc_key_pair( 17 | struct aws_der_decoder *decoder, 18 | struct aws_byte_cursor *out_public_x_coor, 19 | struct aws_byte_cursor *out_public_y_coor, 20 | struct aws_byte_cursor *out_private_d, 21 | enum aws_ecc_curve_name *out_curve_name); 22 | 23 | AWS_EXTERN_C_END 24 | 25 | #endif /* AWS_C_CAL_PRIVATE_ECC_H */ 26 | -------------------------------------------------------------------------------- /include/aws/cal/private/opensslcrypto_common.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_C_CAL_OPENSSLCRYPTO_COMMON_H 2 | #define AWS_C_CAL_OPENSSLCRYPTO_COMMON_H 3 | 4 | /** 5 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 6 | * SPDX-License-Identifier: Apache-2.0. 7 | */ 8 | 9 | #include 10 | 11 | #define OPENSSL_SUPPRESS_DEPRECATED 12 | #include 13 | #include 14 | #include 15 | 16 | #if !defined(OPENSSL_IS_AWSLC) && !defined(OPENSSL_IS_BORINGSSL) 17 | # define OPENSSL_IS_OPENSSL 18 | #endif 19 | 20 | /* 21 | * There are some differences in function definitions between OpenSSL 1.0.2 and 22 | * 1.1.1, aws-lc and boringssl. 23 | * This file defines some common wrappers that abstract away those differences. 24 | * For OpenSSL we currently support building against 1.0.2 or 1.1.1, and can 25 | * detect version used at runtime and dyn load those symbols correctly. 26 | * For OpenSSL 3.0 the code will compile and run, but largely because we disable 27 | * deprecation warnings. 28 | * For aws-lc and boringssl code must be compiled against the same version as 29 | * the runtime lib. 30 | */ 31 | 32 | typedef HMAC_CTX *(*hmac_ctx_new)(void); 33 | typedef void (*hmac_ctx_free)(HMAC_CTX *); 34 | typedef void (*hmac_ctx_init)(HMAC_CTX *); 35 | typedef void (*hmac_ctx_clean_up)(HMAC_CTX *); 36 | typedef int (*hmac_init_ex)(HMAC_CTX *, const void *, size_t, const EVP_MD *, ENGINE *); 37 | typedef int (*hmac_update)(HMAC_CTX *, const unsigned char *, size_t); 38 | typedef int (*hmac_final)(HMAC_CTX *, unsigned char *, unsigned int *); 39 | 40 | /* C standard does not have concept of generic function pointer, but it does 41 | guarantee that function pointer casts will roundtrip when casting to any type and 42 | then back. Use void *(void) as a generic function pointer. */ 43 | typedef void (*crypto_generic_fn_ptr)(void); 44 | 45 | struct openssl_hmac_ctx_table { 46 | hmac_ctx_new new_fn; 47 | hmac_ctx_free free_fn; 48 | hmac_ctx_init init_fn; 49 | hmac_ctx_clean_up clean_up_fn; 50 | hmac_init_ex init_ex_fn; 51 | hmac_update update_fn; 52 | hmac_final final_fn; 53 | 54 | /* There is slight variance between the crypto interfaces. 55 | Note that function pointer casting is undefined behavior. 56 | To workaround the issue, use generic pointer for crypto and let delegate 57 | function cast it back to correct type. 58 | Do not use following fields manually. */ 59 | struct { 60 | crypto_generic_fn_ptr init_ex_fn; 61 | } impl; 62 | }; 63 | 64 | extern struct openssl_hmac_ctx_table *g_aws_openssl_hmac_ctx_table; 65 | 66 | typedef EVP_MD_CTX *(*evp_md_ctx_new)(void); 67 | typedef void (*evp_md_ctx_free)(EVP_MD_CTX *); 68 | typedef int (*evp_md_ctx_digest_init_ex)(EVP_MD_CTX *, const EVP_MD *, ENGINE *); 69 | typedef int (*evp_md_ctx_digest_update)(EVP_MD_CTX *, const void *, size_t); 70 | typedef int (*evp_md_ctx_digest_final_ex)(EVP_MD_CTX *, unsigned char *, unsigned int *); 71 | 72 | struct openssl_evp_md_ctx_table { 73 | evp_md_ctx_new new_fn; 74 | evp_md_ctx_free free_fn; 75 | evp_md_ctx_digest_init_ex init_ex_fn; 76 | evp_md_ctx_digest_update update_fn; 77 | evp_md_ctx_digest_final_ex final_ex_fn; 78 | }; 79 | 80 | extern struct openssl_evp_md_ctx_table *g_aws_openssl_evp_md_ctx_table; 81 | 82 | int aws_reinterpret_lc_evp_error_as_crt(int evp_error, const char *function_name, enum aws_cal_log_subject subject); 83 | 84 | #endif /* AWS_C_CAL_OPENSSLCRYPTO_COMMON_H */ 85 | -------------------------------------------------------------------------------- /include/aws/cal/private/rsa.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_C_CAL_PRIVATE_RSA_H 2 | #define AWS_C_CAL_PRIVATE_RSA_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | struct aws_rsa_key_pair; 14 | struct aws_der_decoder; 15 | 16 | struct aws_rsa_key_vtable { 17 | int (*encrypt)( 18 | const struct aws_rsa_key_pair *key_pair, 19 | enum aws_rsa_encryption_algorithm algorithm, 20 | struct aws_byte_cursor plaintext, 21 | struct aws_byte_buf *out); 22 | int (*decrypt)( 23 | const struct aws_rsa_key_pair *key_pair, 24 | enum aws_rsa_encryption_algorithm algorithm, 25 | struct aws_byte_cursor ciphertext, 26 | struct aws_byte_buf *out); 27 | 28 | int (*sign)( 29 | const struct aws_rsa_key_pair *key_pair, 30 | enum aws_rsa_signature_algorithm algorithm, 31 | struct aws_byte_cursor digest, 32 | struct aws_byte_buf *out); 33 | 34 | int (*verify)( 35 | const struct aws_rsa_key_pair *key_pair, 36 | enum aws_rsa_signature_algorithm algorithm, 37 | struct aws_byte_cursor digest, 38 | struct aws_byte_cursor signature); 39 | }; 40 | 41 | struct aws_rsa_key_pair { 42 | struct aws_allocator *allocator; 43 | struct aws_rsa_key_vtable *vtable; 44 | struct aws_ref_count ref_count; 45 | 46 | size_t key_size_in_bits; 47 | struct aws_byte_buf priv; 48 | struct aws_byte_buf pub; 49 | 50 | void *impl; 51 | }; 52 | 53 | void aws_rsa_key_pair_base_clean_up(struct aws_rsa_key_pair *key_pair); 54 | 55 | /* 56 | * RSAPrivateKey as defined in RFC 8017 (aka PKCS1 format): 57 | * version Version, 58 | * modulus INTEGER, -- n 59 | * publicExponent INTEGER, -- e 60 | * privateExponent INTEGER, -- d 61 | * prime1 INTEGER, -- p 62 | * prime2 INTEGER, -- q 63 | * exponent1 INTEGER, -- d mod (p-1) 64 | * exponent2 INTEGER, -- d mod (q-1) 65 | * coefficient INTEGER, -- (inverse of q) mod p 66 | * otherPrimeInfos OtherPrimeInfos OPTIONAL 67 | * Note: otherPrimeInfos is used for >2 primes RSA cases, which are not very 68 | * common and currently not supported by CRT. Version == 0 indicates 2 prime 69 | * case and version == 1 indicates >2 prime case, hence in practice it will 70 | * always be 0. 71 | */ 72 | struct aws_rsa_private_key_pkcs1 { 73 | /* 74 | * Note: all cursors here point to bignum data for underlying RSA numbers. 75 | * Struct itself does not own the data and points to where ever the data was 76 | * decoded from. 77 | */ 78 | int version; 79 | struct aws_byte_cursor modulus; 80 | struct aws_byte_cursor publicExponent; 81 | struct aws_byte_cursor privateExponent; 82 | struct aws_byte_cursor prime1; 83 | struct aws_byte_cursor prime2; 84 | struct aws_byte_cursor exponent1; 85 | struct aws_byte_cursor exponent2; 86 | struct aws_byte_cursor coefficient; 87 | }; 88 | 89 | AWS_CAL_API int aws_der_decoder_load_private_rsa_pkcs1( 90 | struct aws_der_decoder *decoder, 91 | struct aws_rsa_private_key_pkcs1 *out); 92 | 93 | /* 94 | * RSAPublicKey as defined in RFC 8017 (aka PKCS1 format): 95 | modulus INTEGER, -- n 96 | publicExponent INTEGER -- e 97 | */ 98 | struct aws_rsa_public_key_pkcs1 { 99 | /* 100 | * Note: all cursors here point to bignum data for underlying RSA numbers. 101 | * Struct itself does not own the data and points to where ever the data was 102 | * decoded from. 103 | */ 104 | struct aws_byte_cursor modulus; 105 | struct aws_byte_cursor publicExponent; 106 | }; 107 | 108 | AWS_CAL_API int aws_der_decoder_load_public_rsa_pkcs1( 109 | struct aws_der_decoder *decoder, 110 | struct aws_rsa_public_key_pkcs1 *out); 111 | 112 | /* 113 | * Returns AWS_OP_SUCCESS if key size is supported and raises 114 | * AWS_ERROR_INVALID_ARGUMENT otherwise. 115 | */ 116 | int is_valid_rsa_key_size(size_t key_size_in_bits); 117 | 118 | #endif /* AWS_C_CAL_PRIVATE_RSA_H */ 119 | -------------------------------------------------------------------------------- /include/aws/cal/private/symmetric_cipher_priv.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_SYMMETRIC_CIPHER_PRIV_H 2 | #define AWS_CAL_SYMMETRIC_CIPHER_PRIV_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | 9 | struct aws_symmetric_cipher; 10 | 11 | struct aws_symmetric_cipher_vtable { 12 | const char *alg_name; 13 | const char *provider; 14 | void (*destroy)(struct aws_symmetric_cipher *cipher); 15 | /* reset the cipher to being able to start another encrypt or decrypt operation. 16 | The original IV, Key, Tag etc... will be restored to the current cipher. */ 17 | int (*reset)(struct aws_symmetric_cipher *cipher); 18 | int (*encrypt)(struct aws_symmetric_cipher *cipher, struct aws_byte_cursor to_encrypt, struct aws_byte_buf *out); 19 | int (*decrypt)(struct aws_symmetric_cipher *cipher, struct aws_byte_cursor to_decrypt, struct aws_byte_buf *out); 20 | 21 | int (*finalize_encryption)(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out); 22 | int (*finalize_decryption)(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out); 23 | }; 24 | 25 | struct aws_symmetric_cipher { 26 | struct aws_allocator *allocator; 27 | struct aws_symmetric_cipher_vtable *vtable; 28 | struct aws_byte_buf iv; 29 | struct aws_byte_buf key; 30 | struct aws_byte_buf aad; 31 | struct aws_byte_buf tag; 32 | size_t block_size; 33 | size_t key_length_bits; 34 | /** 35 | deprecated for use, only for backwards compat. 36 | Use state to represent current state of cipher. 37 | good represented if the cipher was initialized 38 | without any errors, ready to process input, 39 | and not finalized yet. This corresponds to 40 | the state AWS_SYMMETRIC_CIPHER_READY. 41 | */ 42 | bool good; 43 | enum aws_symmetric_cipher_state state; 44 | void *impl; 45 | }; 46 | 47 | AWS_EXTERN_C_BEGIN 48 | 49 | /** 50 | * Generates a secure random initialization vector of length len_bytes. If is_counter_mode is set, the final 4 bytes 51 | * will be reserved as a counter and initialized to 1 in big-endian byte-order. 52 | */ 53 | AWS_CAL_API void aws_symmetric_cipher_generate_initialization_vector( 54 | size_t len_bytes, 55 | bool is_counter_mode, 56 | struct aws_byte_buf *out); 57 | 58 | /** 59 | * Generates a secure random symmetric key of length len_bytes. 60 | */ 61 | AWS_CAL_API void aws_symmetric_cipher_generate_key(size_t len_bytes, struct aws_byte_buf *out); 62 | 63 | AWS_EXTERN_C_END 64 | 65 | /* Don't let this one get exported as it should never be used outside of this library (including tests). */ 66 | int aws_symmetric_cipher_try_ensure_sufficient_buffer_space(struct aws_byte_buf *buf, size_t size); 67 | 68 | #endif /* AWS_CAL_SYMMETRIC_CIPHER_PRIV_H */ 69 | -------------------------------------------------------------------------------- /include/aws/cal/rsa.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_RSA_H 2 | #define AWS_CAL_RSA_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | #include 9 | 10 | AWS_PUSH_SANE_WARNING_LEVEL 11 | 12 | struct aws_rsa_key_pair; 13 | 14 | enum aws_rsa_encryption_algorithm { 15 | AWS_CAL_RSA_ENCRYPTION_PKCS1_5, 16 | AWS_CAL_RSA_ENCRYPTION_OAEP_SHA256, 17 | AWS_CAL_RSA_ENCRYPTION_OAEP_SHA512, 18 | }; 19 | 20 | enum aws_rsa_signature_algorithm { 21 | AWS_CAL_RSA_SIGNATURE_PKCS1_5_SHA256, 22 | AWS_CAL_RSA_SIGNATURE_PKCS1_5_SHA1, 23 | AWS_CAL_RSA_SIGNATURE_PSS_SHA256, 24 | }; 25 | 26 | /* 27 | * Note: prefer using standard key sizes - 1024, 2048, 4096. 28 | * Other key sizes will work, but which key sizes are supported may vary by 29 | * platform. Typically, multiples of 64 should work on all platforms. 30 | */ 31 | enum { 32 | AWS_CAL_RSA_MIN_SUPPORTED_KEY_SIZE_IN_BITS = 1024, 33 | AWS_CAL_RSA_MAX_SUPPORTED_KEY_SIZE_IN_BITS = 4096, 34 | }; 35 | 36 | AWS_EXTERN_C_BEGIN 37 | 38 | /** 39 | * Creates an RSA public key from RSAPublicKey as defined in rfc 8017 (aka PKCS1). 40 | * Returns a new instance of aws_rsa_key_pair if the key was successfully built. 41 | * Otherwise returns NULL. 42 | */ 43 | AWS_CAL_API struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_public_key_pkcs1( 44 | struct aws_allocator *allocator, 45 | struct aws_byte_cursor key); 46 | 47 | /** 48 | * Creates an RSA private key from RSAPrivateKey as defined in rfc 8017 (aka PKCS1). 49 | * Returns a new instance of aws_rsa_key_pair if the key was successfully built. 50 | * Otherwise returns NULL. 51 | */ 52 | AWS_CAL_API struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_private_key_pkcs1( 53 | struct aws_allocator *allocator, 54 | struct aws_byte_cursor key); 55 | 56 | /** 57 | * Creates an RSA private key from PrivateKeyInfo as defined in rfc 5208 (aka PKCS8). 58 | * Returns a new instance of aws_rsa_key_pair if the key was successfully built. 59 | * Otherwise returns NULL. 60 | */ 61 | AWS_CAL_API struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_private_key_pkcs8( 62 | struct aws_allocator *allocator, 63 | struct aws_byte_cursor key); 64 | 65 | /** 66 | * Adds one to an RSA key pair's ref count. 67 | * Returns key_pair pointer. 68 | */ 69 | AWS_CAL_API struct aws_rsa_key_pair *aws_rsa_key_pair_acquire(struct aws_rsa_key_pair *key_pair); 70 | 71 | /** 72 | * Subtracts one from an RSA key pair's ref count. If ref count reaches zero, the key pair is destroyed. 73 | * Always returns NULL. 74 | */ 75 | AWS_CAL_API struct aws_rsa_key_pair *aws_rsa_key_pair_release(struct aws_rsa_key_pair *key_pair); 76 | 77 | /** 78 | * Max plaintext size that can be encrypted by the key (i.e. max data size 79 | * supported by the key - bytes needed for padding). 80 | */ 81 | AWS_CAL_API size_t aws_rsa_key_pair_max_encrypt_plaintext_size( 82 | const struct aws_rsa_key_pair *key_pair, 83 | enum aws_rsa_encryption_algorithm algorithm); 84 | 85 | /* 86 | * Uses the key_pair's private key to encrypt the plaintext. The output will be 87 | * in out. out must be large enough to to hold the ciphertext. Check 88 | * aws_rsa_key_pair_block_length() for output upper bound. 89 | */ 90 | AWS_CAL_API int aws_rsa_key_pair_encrypt( 91 | const struct aws_rsa_key_pair *key_pair, 92 | enum aws_rsa_encryption_algorithm algorithm, 93 | struct aws_byte_cursor plaintext, 94 | struct aws_byte_buf *out); 95 | 96 | /* 97 | * Uses the key_pair's private key to decrypt the ciphertext. The output will be 98 | * in out. out must be large enough to to hold the ciphertext. Check 99 | * aws_rsa_key_pair_block_length() for output upper bound. 100 | */ 101 | AWS_CAL_API int aws_rsa_key_pair_decrypt( 102 | const struct aws_rsa_key_pair *key_pair, 103 | enum aws_rsa_encryption_algorithm algorithm, 104 | struct aws_byte_cursor ciphertext, 105 | struct aws_byte_buf *out); 106 | 107 | /* 108 | * Max size for a block supported by a given key pair. 109 | */ 110 | AWS_CAL_API size_t aws_rsa_key_pair_block_length(const struct aws_rsa_key_pair *key_pair); 111 | 112 | /** 113 | * Uses the key_pair's private key to sign message. The output will be in out. out must be large enough 114 | * to hold the signature. Check aws_rsa_key_pair_signature_length() for the appropriate size. 115 | * 116 | * It is the callers job to make sure message is the appropriate cryptographic digest for this operation. It's usually 117 | * something like a SHA256. 118 | */ 119 | AWS_CAL_API int aws_rsa_key_pair_sign_message( 120 | const struct aws_rsa_key_pair *key_pair, 121 | enum aws_rsa_signature_algorithm algorithm, 122 | struct aws_byte_cursor digest, 123 | struct aws_byte_buf *out); 124 | 125 | /** 126 | * Uses the key_pair's public key to verify signature of message. 127 | * 128 | * It is the callers job to make sure message is the appropriate cryptographic digest for this operation. It's usually 129 | * something like a SHA256. 130 | * 131 | * returns AWS_OP_SUCCESS if the signature is valid. 132 | * raises AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED if signature validation failed 133 | */ 134 | AWS_CAL_API int aws_rsa_key_pair_verify_signature( 135 | const struct aws_rsa_key_pair *key_pair, 136 | enum aws_rsa_signature_algorithm algorithm, 137 | struct aws_byte_cursor digest, 138 | struct aws_byte_cursor signature); 139 | 140 | /* 141 | * Max size for a signature supported by a given key pair. 142 | */ 143 | AWS_CAL_API size_t aws_rsa_key_pair_signature_length(const struct aws_rsa_key_pair *key_pair); 144 | 145 | enum aws_rsa_key_export_format { 146 | AWS_CAL_RSA_KEY_EXPORT_PKCS1, 147 | }; 148 | 149 | /* 150 | * Get public key for the key pair. 151 | * Inits out to a copy of key. 152 | * Any encoding on top of that (ex. b64) is left up to user. 153 | * Note: this function is currently not supported on windows for generated keys. 154 | */ 155 | AWS_CAL_API int aws_rsa_key_pair_get_public_key( 156 | const struct aws_rsa_key_pair *key_pair, 157 | enum aws_rsa_key_export_format format, 158 | struct aws_byte_buf *out); 159 | 160 | /* 161 | * Get private key for the key pair. 162 | * Inits out to a copy of key. 163 | * Any encoding on top of that (ex. b64) is left up to user. 164 | * Note: this function is currently not supported on Windows for generated keys. 165 | */ 166 | AWS_CAL_API int aws_rsa_key_pair_get_private_key( 167 | const struct aws_rsa_key_pair *key_pair, 168 | enum aws_rsa_key_export_format format, 169 | struct aws_byte_buf *out); 170 | 171 | AWS_EXTERN_C_END 172 | 173 | AWS_POP_SANE_WARNING_LEVEL 174 | 175 | #endif /* AWS_CAL_RSA_H */ 176 | -------------------------------------------------------------------------------- /source/cal.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #define AWS_DEFINE_ERROR_INFO_CAL(CODE, STR) [(CODE) - 0x1C00] = AWS_DEFINE_ERROR_INFO(CODE, STR, "aws-c-cal") 10 | 11 | static struct aws_error_info s_errors[] = { 12 | AWS_DEFINE_ERROR_INFO_CAL(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED, "Verify on a cryptographic signature failed."), 13 | AWS_DEFINE_ERROR_INFO_CAL( 14 | AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT, 15 | "An attempt was made to perform an " 16 | "Asymmetric cryptographic operation with the" 17 | "wrong key component. For example, attempt to" 18 | "verify a signature with a private key or " 19 | "sign a message with a public key."), 20 | AWS_DEFINE_ERROR_INFO_CAL( 21 | AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM, 22 | "A key length was used for an algorithm that needs a different key length."), 23 | AWS_DEFINE_ERROR_INFO_CAL( 24 | AWS_ERROR_CAL_UNKNOWN_OBJECT_IDENTIFIER, 25 | "An ASN.1 OID was encountered that wasn't expected or understood. Most likely, an unsupported algorithm was " 26 | "encountered."), 27 | AWS_DEFINE_ERROR_INFO_CAL( 28 | AWS_ERROR_CAL_MALFORMED_ASN1_ENCOUNTERED, 29 | "An ASN.1 DER decoding operation failed on malformed input."), 30 | AWS_DEFINE_ERROR_INFO_CAL( 31 | AWS_ERROR_CAL_MISMATCHED_DER_TYPE, 32 | "An invalid DER type was requested during encoding/decoding."), 33 | AWS_DEFINE_ERROR_INFO_CAL( 34 | AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM, 35 | "The specified algorithm is unsupported on this platform."), 36 | AWS_DEFINE_ERROR_INFO_CAL( 37 | AWS_ERROR_CAL_BUFFER_TOO_LARGE_FOR_ALGORITHM, 38 | "The input passed to a cipher algorithm was too large for that algorithm. Consider breaking the input into " 39 | "smaller chunks."), 40 | AWS_DEFINE_ERROR_INFO_CAL( 41 | AWS_ERROR_CAL_INVALID_CIPHER_MATERIAL_SIZE_FOR_ALGORITHM, 42 | "A cipher material such as an initialization vector or tag was an incorrect size for the selected algorithm."), 43 | AWS_DEFINE_ERROR_INFO_CAL( 44 | AWS_ERROR_CAL_DER_UNSUPPORTED_NEGATIVE_INT, 45 | "DER decoder does support negative integers."), 46 | AWS_DEFINE_ERROR_INFO_CAL(AWS_ERROR_CAL_UNSUPPORTED_KEY_FORMAT, "Key format is not supported."), 47 | AWS_DEFINE_ERROR_INFO_CAL( 48 | AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED, 49 | "Unknown error when calling underlying Crypto library.")}; 50 | 51 | static struct aws_error_info_list s_list = { 52 | .error_list = s_errors, 53 | .count = AWS_ARRAY_SIZE(s_errors), 54 | }; 55 | 56 | static struct aws_log_subject_info s_cal_log_subject_infos[] = { 57 | DEFINE_LOG_SUBJECT_INFO( 58 | AWS_LS_CAL_GENERAL, 59 | "aws-c-cal", 60 | "Subject for Cal logging that doesn't belong to any particular category"), 61 | DEFINE_LOG_SUBJECT_INFO(AWS_LS_CAL_ECC, "ecc", "Subject for elliptic curve cryptography specific logging."), 62 | DEFINE_LOG_SUBJECT_INFO(AWS_LS_CAL_HASH, "hash", "Subject for hashing specific logging."), 63 | DEFINE_LOG_SUBJECT_INFO(AWS_LS_CAL_HMAC, "hmac", "Subject for hmac specific logging."), 64 | DEFINE_LOG_SUBJECT_INFO(AWS_LS_CAL_DER, "der", "Subject for der specific logging."), 65 | DEFINE_LOG_SUBJECT_INFO( 66 | AWS_LS_CAL_LIBCRYPTO_RESOLVE, 67 | "libcrypto_resolve", 68 | "Subject for libcrypto symbol resolution logging."), 69 | DEFINE_LOG_SUBJECT_INFO(AWS_LS_CAL_RSA, "rsa", "Subject for rsa cryptography specific logging."), 70 | DEFINE_LOG_SUBJECT_INFO(AWS_LS_CAL_ED25519, "ed25519", "Subject for ed25519 cryptography specific logging."), 71 | }; 72 | 73 | static struct aws_log_subject_info_list s_cal_log_subject_list = { 74 | .subject_list = s_cal_log_subject_infos, 75 | .count = AWS_ARRAY_SIZE(s_cal_log_subject_infos), 76 | }; 77 | 78 | #ifndef BYO_CRYPTO 79 | extern void aws_cal_platform_init(struct aws_allocator *allocator); 80 | extern void aws_cal_platform_clean_up(void); 81 | extern void aws_cal_platform_thread_clean_up(void); 82 | #endif /* BYO_CRYPTO */ 83 | 84 | static bool s_cal_library_initialized = false; 85 | 86 | void aws_cal_library_init(struct aws_allocator *allocator) { 87 | if (!s_cal_library_initialized) { 88 | aws_common_library_init(allocator); 89 | aws_register_error_info(&s_list); 90 | aws_register_log_subject_info_list(&s_cal_log_subject_list); 91 | #ifndef BYO_CRYPTO 92 | aws_cal_platform_init(allocator); 93 | #endif /* BYO_CRYPTO */ 94 | s_cal_library_initialized = true; 95 | } 96 | } 97 | void aws_cal_library_clean_up(void) { 98 | if (s_cal_library_initialized) { 99 | s_cal_library_initialized = false; 100 | #ifndef BYO_CRYPTO 101 | aws_cal_platform_clean_up(); 102 | #endif /* BYO_CRYPTO */ 103 | aws_unregister_log_subject_info_list(&s_cal_log_subject_list); 104 | aws_unregister_error_info(&s_list); 105 | aws_common_library_clean_up(); 106 | } 107 | } 108 | 109 | void aws_cal_thread_clean_up(void) { 110 | #ifndef BYO_CRYPTO 111 | aws_cal_platform_thread_clean_up(); 112 | #endif /* BYO_CRYPTO */ 113 | } 114 | -------------------------------------------------------------------------------- /source/darwin/commoncrypto_hmac.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | 7 | #include 8 | 9 | static void s_destroy(struct aws_hmac *hmac); 10 | static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac); 11 | static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output); 12 | 13 | static struct aws_hmac_vtable s_sha256_hmac_vtable = { 14 | .destroy = s_destroy, 15 | .update = s_update, 16 | .finalize = s_finalize, 17 | .alg_name = "SHA256 HMAC", 18 | .provider = "CommonCrypto", 19 | }; 20 | 21 | struct cc_hmac { 22 | struct aws_hmac hmac; 23 | CCHmacContext cc_hmac_ctx; 24 | }; 25 | 26 | struct aws_hmac *aws_sha256_hmac_default_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { 27 | AWS_ASSERT(secret->ptr); 28 | 29 | struct cc_hmac *cc_hmac = aws_mem_acquire(allocator, sizeof(struct cc_hmac)); 30 | 31 | if (!cc_hmac) { 32 | return NULL; 33 | } 34 | 35 | cc_hmac->hmac.allocator = allocator; 36 | cc_hmac->hmac.vtable = &s_sha256_hmac_vtable; 37 | cc_hmac->hmac.impl = cc_hmac; 38 | cc_hmac->hmac.digest_size = AWS_SHA256_HMAC_LEN; 39 | cc_hmac->hmac.good = true; 40 | 41 | CCHmacInit(&cc_hmac->cc_hmac_ctx, kCCHmacAlgSHA256, secret->ptr, (CC_LONG)secret->len); 42 | 43 | return &cc_hmac->hmac; 44 | } 45 | 46 | static void s_destroy(struct aws_hmac *hmac) { 47 | struct cc_hmac *ctx = hmac->impl; 48 | aws_mem_release(hmac->allocator, ctx); 49 | } 50 | 51 | static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac) { 52 | if (!hmac->good) { 53 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 54 | } 55 | 56 | struct cc_hmac *ctx = hmac->impl; 57 | 58 | CCHmacUpdate(&ctx->cc_hmac_ctx, to_hmac->ptr, (CC_LONG)to_hmac->len); 59 | return AWS_OP_SUCCESS; 60 | } 61 | 62 | static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output) { 63 | if (!hmac->good) { 64 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 65 | } 66 | 67 | struct cc_hmac *ctx = hmac->impl; 68 | 69 | size_t buffer_len = output->capacity - output->len; 70 | 71 | if (buffer_len < hmac->digest_size) { 72 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 73 | } 74 | 75 | CCHmacFinal(&ctx->cc_hmac_ctx, output->buffer + output->len); 76 | hmac->good = false; 77 | output->len += hmac->digest_size; 78 | return AWS_OP_SUCCESS; 79 | } 80 | -------------------------------------------------------------------------------- /source/darwin/commoncrypto_md5.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | 7 | #include 8 | 9 | #pragma clang diagnostic push 10 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 11 | 12 | static void s_destroy(struct aws_hash *hash); 13 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); 14 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); 15 | 16 | static struct aws_hash_vtable s_vtable = { 17 | .destroy = s_destroy, 18 | .update = s_update, 19 | .finalize = s_finalize, 20 | .alg_name = "MD5", 21 | .provider = "CommonCrypto", 22 | }; 23 | 24 | struct cc_md5_hash { 25 | struct aws_hash hash; 26 | CC_MD5_CTX cc_hash; 27 | }; 28 | struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) { 29 | struct cc_md5_hash *cc_md5_hash = aws_mem_acquire(allocator, sizeof(struct cc_md5_hash)); 30 | 31 | if (!cc_md5_hash) { 32 | return NULL; 33 | } 34 | 35 | cc_md5_hash->hash.allocator = allocator; 36 | cc_md5_hash->hash.vtable = &s_vtable; 37 | cc_md5_hash->hash.digest_size = AWS_MD5_LEN; 38 | cc_md5_hash->hash.impl = cc_md5_hash; 39 | cc_md5_hash->hash.good = true; 40 | 41 | CC_MD5_Init(&cc_md5_hash->cc_hash); 42 | return &cc_md5_hash->hash; 43 | } 44 | 45 | static void s_destroy(struct aws_hash *hash) { 46 | struct cc_md5_hash *ctx = hash->impl; 47 | aws_mem_release(hash->allocator, ctx); 48 | } 49 | 50 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { 51 | if (!hash->good) { 52 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 53 | } 54 | 55 | struct cc_md5_hash *ctx = hash->impl; 56 | 57 | CC_MD5_Update(&ctx->cc_hash, to_hash->ptr, (CC_LONG)to_hash->len); 58 | return AWS_OP_SUCCESS; 59 | } 60 | 61 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { 62 | if (!hash->good) { 63 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 64 | } 65 | 66 | struct cc_md5_hash *ctx = hash->impl; 67 | 68 | size_t buffer_len = output->capacity - output->len; 69 | 70 | if (buffer_len < hash->digest_size) { 71 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 72 | } 73 | 74 | CC_MD5_Final(output->buffer + output->len, &ctx->cc_hash); 75 | hash->good = false; 76 | output->len += hash->digest_size; 77 | return AWS_OP_SUCCESS; 78 | } 79 | 80 | #pragma clang diagnostic pop 81 | -------------------------------------------------------------------------------- /source/darwin/commoncrypto_platform_init.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 8 | # include 9 | #endif 10 | 11 | void aws_cal_platform_init(struct aws_allocator *allocator) { 12 | (void)allocator; 13 | } 14 | 15 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 16 | void __attribute__((destructor)) s_cal_crypto_shutdown(void) { 17 | AWSLC_thread_local_shutdown(); 18 | } 19 | #endif 20 | 21 | void aws_cal_platform_clean_up(void) { 22 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 23 | AWSLC_thread_local_clear(); 24 | #endif 25 | } 26 | 27 | void aws_cal_platform_thread_clean_up(void) { 28 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 29 | AWSLC_thread_local_clear(); 30 | #endif 31 | } 32 | -------------------------------------------------------------------------------- /source/darwin/commoncrypto_sha1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | #include 9 | 10 | static void s_destroy(struct aws_hash *hash); 11 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); 12 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); 13 | 14 | static struct aws_hash_vtable s_vtable = { 15 | .destroy = s_destroy, 16 | .update = s_update, 17 | .finalize = s_finalize, 18 | .alg_name = "SHA1", 19 | .provider = "CommonCrypto", 20 | }; 21 | 22 | struct cc_sha1_hash { 23 | struct aws_hash hash; 24 | CC_SHA1_CTX cc_hash; 25 | }; 26 | 27 | struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator) { 28 | struct cc_sha1_hash *sha1_hash = aws_mem_acquire(allocator, sizeof(struct cc_sha1_hash)); 29 | 30 | if (!sha1_hash) { 31 | return NULL; 32 | } 33 | 34 | sha1_hash->hash.allocator = allocator; 35 | sha1_hash->hash.vtable = &s_vtable; 36 | sha1_hash->hash.impl = sha1_hash; 37 | sha1_hash->hash.digest_size = AWS_SHA1_LEN; 38 | sha1_hash->hash.good = true; 39 | 40 | CC_SHA1_Init(&sha1_hash->cc_hash); 41 | return &sha1_hash->hash; 42 | } 43 | 44 | static void s_destroy(struct aws_hash *hash) { 45 | struct cc_sha1_hash *ctx = hash->impl; 46 | aws_mem_release(hash->allocator, ctx); 47 | } 48 | 49 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { 50 | if (!hash->good) { 51 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 52 | } 53 | 54 | struct cc_sha1_hash *ctx = hash->impl; 55 | 56 | CC_SHA1_Update(&ctx->cc_hash, to_hash->ptr, (CC_LONG)to_hash->len); 57 | return AWS_OP_SUCCESS; 58 | } 59 | 60 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { 61 | if (!hash->good) { 62 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 63 | } 64 | 65 | struct cc_sha1_hash *ctx = hash->impl; 66 | 67 | size_t buffer_len = output->capacity - output->len; 68 | 69 | if (buffer_len < hash->digest_size) { 70 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 71 | } 72 | 73 | CC_SHA1_Final(output->buffer + output->len, &ctx->cc_hash); 74 | hash->good = false; 75 | output->len += hash->digest_size; 76 | return AWS_OP_SUCCESS; 77 | } 78 | -------------------------------------------------------------------------------- /source/darwin/commoncrypto_sha256.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | 7 | #include 8 | 9 | static void s_destroy(struct aws_hash *hash); 10 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); 11 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); 12 | 13 | static struct aws_hash_vtable s_vtable = { 14 | .destroy = s_destroy, 15 | .update = s_update, 16 | .finalize = s_finalize, 17 | .alg_name = "SHA256", 18 | .provider = "CommonCrypto", 19 | }; 20 | 21 | struct cc_sha256_hash { 22 | struct aws_hash hash; 23 | CC_SHA256_CTX cc_hash; 24 | }; 25 | 26 | struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) { 27 | struct cc_sha256_hash *sha256_hash = aws_mem_acquire(allocator, sizeof(struct cc_sha256_hash)); 28 | 29 | if (!sha256_hash) { 30 | return NULL; 31 | } 32 | 33 | sha256_hash->hash.allocator = allocator; 34 | sha256_hash->hash.vtable = &s_vtable; 35 | sha256_hash->hash.impl = sha256_hash; 36 | sha256_hash->hash.digest_size = AWS_SHA256_LEN; 37 | sha256_hash->hash.good = true; 38 | 39 | CC_SHA256_Init(&sha256_hash->cc_hash); 40 | return &sha256_hash->hash; 41 | } 42 | 43 | static void s_destroy(struct aws_hash *hash) { 44 | struct cc_sha256_hash *ctx = hash->impl; 45 | aws_mem_release(hash->allocator, ctx); 46 | } 47 | 48 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { 49 | if (!hash->good) { 50 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 51 | } 52 | 53 | struct cc_sha256_hash *ctx = hash->impl; 54 | 55 | CC_SHA256_Update(&ctx->cc_hash, to_hash->ptr, (CC_LONG)to_hash->len); 56 | return AWS_OP_SUCCESS; 57 | } 58 | 59 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { 60 | if (!hash->good) { 61 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 62 | } 63 | 64 | struct cc_sha256_hash *ctx = hash->impl; 65 | 66 | size_t buffer_len = output->capacity - output->len; 67 | 68 | if (buffer_len < hash->digest_size) { 69 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 70 | } 71 | 72 | CC_SHA256_Final(output->buffer + output->len, &ctx->cc_hash); 73 | hash->good = false; 74 | output->len += hash->digest_size; 75 | return AWS_OP_SUCCESS; 76 | } 77 | -------------------------------------------------------------------------------- /source/ed25519.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | struct aws_ed25519_key_pair_impl; 10 | 11 | #ifndef BYO_CRYPTO 12 | 13 | extern struct aws_ed25519_key_pair_impl *aws_ed25519_key_pair_new_generate_impl(struct aws_allocator *allocator); 14 | 15 | extern void aws_ed25519_key_pair_destroy_impl(struct aws_ed25519_key_pair_impl *key_pair_impl); 16 | 17 | extern int aws_ed25519_key_pair_get_public_key_impl( 18 | const struct aws_ed25519_key_pair_impl *key_pair, 19 | enum aws_ed25519_key_export_format format, 20 | struct aws_byte_buf *out); 21 | 22 | extern size_t aws_ed25519_key_pair_get_public_key_size_impl(enum aws_ed25519_key_export_format format); 23 | 24 | extern int aws_ed25519_key_pair_get_private_key_impl( 25 | const struct aws_ed25519_key_pair_impl *key_pair, 26 | enum aws_ed25519_key_export_format format, 27 | struct aws_byte_buf *out); 28 | 29 | extern size_t aws_ed25519_key_pair_get_private_key_size_impl(enum aws_ed25519_key_export_format format); 30 | 31 | #else /* BYO_CRYPTO */ 32 | 33 | struct aws_ed25519_key_pair_impl *aws_ed25519_key_pair_new_generate_impl(struct aws_allocator *allocator) { 34 | (void)allocator; 35 | abort(); 36 | } 37 | 38 | void aws_ed25519_key_pair_destroy_impl(struct aws_ed25519_key_pair_impl *key_pair_impl) { 39 | (void)key_pair_impl; 40 | abort(); 41 | } 42 | 43 | int aws_ed25519_key_pair_get_public_key_impl( 44 | const struct aws_ed25519_key_pair_impl *key_pair, 45 | enum aws_ed25519_key_export_format format, 46 | struct aws_byte_buf *out) { 47 | (void)key_pair; 48 | (void)format; 49 | (void)out; 50 | abort(); 51 | } 52 | 53 | size_t aws_ed25519_key_pair_get_public_key_size_impl(enum aws_ed25519_key_export_format format) { 54 | (void)format; 55 | abort(); 56 | } 57 | 58 | int aws_ed25519_key_pair_get_private_key_impl( 59 | const struct aws_ed25519_key_pair_impl *key_pair, 60 | enum aws_ed25519_key_export_format format, 61 | struct aws_byte_buf *out) { 62 | (void)key_pair; 63 | (void)format; 64 | (void)out; 65 | abort(); 66 | } 67 | 68 | size_t aws_ed25519_key_pair_get_private_key_size_impl(enum aws_ed25519_key_export_format format) { 69 | (void)format; 70 | abort(); 71 | } 72 | 73 | #endif /* BYO_CRYPTO */ 74 | 75 | struct aws_ed25519_key_pair { 76 | struct aws_allocator *allocator; 77 | struct aws_ref_count ref_count; 78 | 79 | struct aws_ed25519_key_pair_impl *key; 80 | }; 81 | 82 | static void s_ed25519_destroy_key(void *key_pair) { 83 | if (key_pair == NULL) { 84 | return; 85 | } 86 | 87 | struct aws_ed25519_key_pair *ed25519_key_pair = (struct aws_ed25519_key_pair *)(key_pair); 88 | 89 | if (ed25519_key_pair->key != NULL) { 90 | aws_ed25519_key_pair_destroy_impl(ed25519_key_pair->key); 91 | } 92 | 93 | aws_mem_release(ed25519_key_pair->allocator, ed25519_key_pair); 94 | } 95 | 96 | struct aws_ed25519_key_pair *aws_ed25519_key_pair_new_generate(struct aws_allocator *allocator) { 97 | 98 | struct aws_ed25519_key_pair_impl *key_impl = aws_ed25519_key_pair_new_generate_impl(allocator); 99 | 100 | if (key_impl == NULL) { 101 | return NULL; 102 | } 103 | 104 | struct aws_ed25519_key_pair *key_pair = aws_mem_calloc(allocator, 1, sizeof(struct aws_ed25519_key_pair)); 105 | 106 | aws_ref_count_init(&key_pair->ref_count, key_pair, s_ed25519_destroy_key); 107 | key_pair->allocator = allocator; 108 | key_pair->key = key_impl; 109 | 110 | return key_pair; 111 | } 112 | 113 | struct aws_ed25519_key_pair *aws_ed25519_key_pair_acquire(struct aws_ed25519_key_pair *key_pair) { 114 | if (key_pair != NULL) { 115 | aws_ref_count_acquire(&key_pair->ref_count); 116 | } 117 | return key_pair; 118 | } 119 | 120 | struct aws_ed25519_key_pair *aws_ed25519_key_pair_release(struct aws_ed25519_key_pair *key_pair) { 121 | if (key_pair != NULL) { 122 | aws_ref_count_release(&key_pair->ref_count); 123 | } 124 | return NULL; 125 | } 126 | 127 | int aws_ed25519_key_pair_get_public_key( 128 | const struct aws_ed25519_key_pair *key_pair, 129 | enum aws_ed25519_key_export_format format, 130 | struct aws_byte_buf *out) { 131 | return aws_ed25519_key_pair_get_public_key_impl(key_pair->key, format, out); 132 | } 133 | 134 | size_t aws_ed25519_key_pair_get_public_key_size(enum aws_ed25519_key_export_format format) { 135 | return aws_ed25519_key_pair_get_public_key_size_impl(format); 136 | } 137 | 138 | int aws_ed25519_key_pair_get_private_key( 139 | const struct aws_ed25519_key_pair *key_pair, 140 | enum aws_ed25519_key_export_format format, 141 | struct aws_byte_buf *out) { 142 | return aws_ed25519_key_pair_get_private_key_impl(key_pair->key, format, out); 143 | } 144 | 145 | size_t aws_ed25519_key_pair_get_private_key_size(enum aws_ed25519_key_export_format format) { 146 | return aws_ed25519_key_pair_get_private_key_size_impl(format); 147 | } 148 | -------------------------------------------------------------------------------- /source/hash.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | 7 | #ifndef BYO_CRYPTO 8 | extern struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator); 9 | extern struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator); 10 | extern struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator); 11 | 12 | static aws_hash_new_fn *s_sha256_new_fn = aws_sha256_default_new; 13 | static aws_hash_new_fn *s_sha1_new_fn = aws_sha1_default_new; 14 | static aws_hash_new_fn *s_md5_new_fn = aws_md5_default_new; 15 | #else 16 | static struct aws_hash *aws_hash_new_abort(struct aws_allocator *allocator) { 17 | (void)allocator; 18 | abort(); 19 | } 20 | 21 | static aws_hash_new_fn *s_sha256_new_fn = aws_hash_new_abort; 22 | static aws_hash_new_fn *s_sha1_new_fn = aws_hash_new_abort; 23 | static aws_hash_new_fn *s_md5_new_fn = aws_hash_new_abort; 24 | #endif 25 | 26 | struct aws_hash *aws_sha1_new(struct aws_allocator *allocator) { 27 | return s_sha1_new_fn(allocator); 28 | } 29 | 30 | struct aws_hash *aws_sha256_new(struct aws_allocator *allocator) { 31 | return s_sha256_new_fn(allocator); 32 | } 33 | 34 | struct aws_hash *aws_md5_new(struct aws_allocator *allocator) { 35 | return s_md5_new_fn(allocator); 36 | } 37 | 38 | void aws_set_md5_new_fn(aws_hash_new_fn *fn) { 39 | s_md5_new_fn = fn; 40 | } 41 | 42 | void aws_set_sha256_new_fn(aws_hash_new_fn *fn) { 43 | s_sha256_new_fn = fn; 44 | } 45 | 46 | void aws_set_sha1_new_fn(aws_hash_new_fn *fn) { 47 | s_sha1_new_fn = fn; 48 | } 49 | 50 | void aws_hash_destroy(struct aws_hash *hash) { 51 | hash->vtable->destroy(hash); 52 | } 53 | 54 | int aws_hash_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { 55 | return hash->vtable->update(hash, to_hash); 56 | } 57 | 58 | int aws_hash_finalize(struct aws_hash *hash, struct aws_byte_buf *output, size_t truncate_to) { 59 | 60 | if (truncate_to && truncate_to < hash->digest_size) { 61 | size_t available_buffer = output->capacity - output->len; 62 | if (available_buffer < truncate_to) { 63 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 64 | } 65 | 66 | uint8_t tmp_output[128] = {0}; 67 | AWS_ASSERT(sizeof(tmp_output) >= hash->digest_size); 68 | 69 | struct aws_byte_buf tmp_out_buf = aws_byte_buf_from_array(tmp_output, sizeof(tmp_output)); 70 | tmp_out_buf.len = 0; 71 | 72 | if (hash->vtable->finalize(hash, &tmp_out_buf)) { 73 | return AWS_OP_ERR; 74 | } 75 | 76 | memcpy(output->buffer + output->len, tmp_output, truncate_to); 77 | output->len += truncate_to; 78 | return AWS_OP_SUCCESS; 79 | } 80 | 81 | return hash->vtable->finalize(hash, output); 82 | } 83 | 84 | static inline int compute_hash( 85 | struct aws_hash *hash, 86 | const struct aws_byte_cursor *input, 87 | struct aws_byte_buf *output, 88 | size_t truncate_to) { 89 | if (!hash) { 90 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 91 | } 92 | 93 | if (aws_hash_update(hash, input)) { 94 | aws_hash_destroy(hash); 95 | return AWS_OP_ERR; 96 | } 97 | 98 | if (aws_hash_finalize(hash, output, truncate_to)) { 99 | aws_hash_destroy(hash); 100 | return AWS_OP_ERR; 101 | } 102 | 103 | aws_hash_destroy(hash); 104 | return AWS_OP_SUCCESS; 105 | } 106 | 107 | int aws_md5_compute( 108 | struct aws_allocator *allocator, 109 | const struct aws_byte_cursor *input, 110 | struct aws_byte_buf *output, 111 | size_t truncate_to) { 112 | return compute_hash(aws_md5_new(allocator), input, output, truncate_to); 113 | } 114 | 115 | int aws_sha256_compute( 116 | struct aws_allocator *allocator, 117 | const struct aws_byte_cursor *input, 118 | struct aws_byte_buf *output, 119 | size_t truncate_to) { 120 | return compute_hash(aws_sha256_new(allocator), input, output, truncate_to); 121 | } 122 | 123 | int aws_sha1_compute( 124 | struct aws_allocator *allocator, 125 | const struct aws_byte_cursor *input, 126 | struct aws_byte_buf *output, 127 | size_t truncate_to) { 128 | return compute_hash(aws_sha1_new(allocator), input, output, truncate_to); 129 | } 130 | -------------------------------------------------------------------------------- /source/hmac.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | 7 | #ifndef BYO_CRYPTO 8 | extern struct aws_hmac *aws_sha256_hmac_default_new( 9 | struct aws_allocator *allocator, 10 | const struct aws_byte_cursor *secret); 11 | static aws_hmac_new_fn *s_sha256_hmac_new_fn = aws_sha256_hmac_default_new; 12 | #else 13 | static struct aws_hmac *aws_hmac_new_abort(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { 14 | (void)allocator; 15 | (void)secret; 16 | abort(); 17 | } 18 | 19 | static aws_hmac_new_fn *s_sha256_hmac_new_fn = aws_hmac_new_abort; 20 | #endif 21 | 22 | struct aws_hmac *aws_sha256_hmac_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { 23 | return s_sha256_hmac_new_fn(allocator, secret); 24 | } 25 | 26 | void aws_set_sha256_hmac_new_fn(aws_hmac_new_fn *fn) { 27 | s_sha256_hmac_new_fn = fn; 28 | } 29 | 30 | void aws_hmac_destroy(struct aws_hmac *hmac) { 31 | hmac->vtable->destroy(hmac); 32 | } 33 | 34 | int aws_hmac_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac) { 35 | return hmac->vtable->update(hmac, to_hmac); 36 | } 37 | 38 | int aws_hmac_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output, size_t truncate_to) { 39 | if (truncate_to && truncate_to < hmac->digest_size) { 40 | size_t available_buffer = output->capacity - output->len; 41 | if (available_buffer < truncate_to) { 42 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 43 | } 44 | 45 | uint8_t tmp_output[128] = {0}; 46 | AWS_ASSERT(sizeof(tmp_output) >= hmac->digest_size); 47 | 48 | struct aws_byte_buf tmp_out_buf = aws_byte_buf_from_array(tmp_output, sizeof(tmp_output)); 49 | tmp_out_buf.len = 0; 50 | 51 | if (hmac->vtable->finalize(hmac, &tmp_out_buf)) { 52 | return AWS_OP_ERR; 53 | } 54 | 55 | memcpy(output->buffer + output->len, tmp_output, truncate_to); 56 | output->len += truncate_to; 57 | return AWS_OP_SUCCESS; 58 | } 59 | 60 | return hmac->vtable->finalize(hmac, output); 61 | } 62 | 63 | int aws_sha256_hmac_compute( 64 | struct aws_allocator *allocator, 65 | const struct aws_byte_cursor *secret, 66 | const struct aws_byte_cursor *to_hmac, 67 | struct aws_byte_buf *output, 68 | size_t truncate_to) { 69 | struct aws_hmac *hmac = aws_sha256_hmac_new(allocator, secret); 70 | 71 | if (!hmac) { 72 | return AWS_OP_ERR; 73 | } 74 | 75 | if (aws_hmac_update(hmac, to_hmac)) { 76 | aws_hmac_destroy(hmac); 77 | return AWS_OP_ERR; 78 | } 79 | 80 | if (aws_hmac_finalize(hmac, output, truncate_to)) { 81 | aws_hmac_destroy(hmac); 82 | return AWS_OP_ERR; 83 | } 84 | 85 | aws_hmac_destroy(hmac); 86 | return AWS_OP_SUCCESS; 87 | } 88 | -------------------------------------------------------------------------------- /source/shared/ed25519_noop.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | 8 | struct aws_ed25519_key_pair_impl; 9 | 10 | void aws_ed25519_key_pair_destroy_impl(struct aws_ed25519_key_pair_impl *key_pair) { 11 | AWS_FATAL_ASSERT(key_pair == NULL); 12 | return; 13 | } 14 | 15 | struct aws_ed25519_key_pair_impl *aws_ed25519_key_pair_new_generate_impl(struct aws_allocator *allocator) { 16 | (void)allocator; 17 | aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM); 18 | return NULL; 19 | } 20 | 21 | int aws_ed25519_key_pair_get_public_key_impl( 22 | const struct aws_ed25519_key_pair_impl *key_pair, 23 | enum aws_ed25519_key_export_format format, 24 | struct aws_byte_buf *out) { 25 | (void)key_pair; 26 | (void)format; 27 | (void)out; 28 | return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM); 29 | } 30 | 31 | size_t aws_ed25519_key_pair_get_public_key_size_impl(enum aws_ed25519_key_export_format format) { 32 | (void)format; 33 | AWS_FATAL_ASSERT(0); 34 | return 0; 35 | } 36 | 37 | int aws_ed25519_key_pair_get_private_key_impl( 38 | const struct aws_ed25519_key_pair_impl *key_pair, 39 | enum aws_ed25519_key_export_format format, 40 | struct aws_byte_buf *out) { 41 | (void)key_pair; 42 | (void)format; 43 | (void)out; 44 | return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM); 45 | } 46 | 47 | size_t aws_ed25519_key_pair_get_private_key_size_impl(enum aws_ed25519_key_export_format format) { 48 | (void)format; 49 | AWS_FATAL_ASSERT(0); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /source/shared/lccrypto_common.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #define OPENSSL_SUPPRESS_DEPRECATED 10 | #include 11 | #include 12 | 13 | #if defined(OPENSSL_IS_OPENSSL) 14 | /*Error defines were part of evp.h in 1.0.x and were moved to evperr.h in 1.1.0*/ 15 | # if OPENSSL_VERSION_NUMBER >= 0x10100000L 16 | # include 17 | # endif 18 | #else 19 | # include 20 | #endif 21 | 22 | /* 23 | * Transforms evp error code into crt error code and raises it as necessary. 24 | * All evp functions follow the same: 25 | * >= 1 for success 26 | * <= 0 for failure 27 | * -2 always indicates incorrect algo for operation 28 | */ 29 | int aws_reinterpret_lc_evp_error_as_crt(int evp_error, const char *function_name, enum aws_cal_log_subject subject) { 30 | if (evp_error > 0) { 31 | return AWS_OP_SUCCESS; 32 | } 33 | 34 | /* AWS-LC/BoringSSL error code is uint32_t, but OpenSSL uses unsigned long. */ 35 | #if defined(OPENSSL_IS_OPENSSL) 36 | uint32_t error = ERR_peek_error(); 37 | #else 38 | unsigned long error = ERR_peek_error(); 39 | #endif 40 | 41 | int crt_error = AWS_OP_ERR; 42 | const char *error_message = ERR_reason_error_string(error); 43 | 44 | if (evp_error == -2) { 45 | crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM; 46 | goto on_error; 47 | } 48 | 49 | if (ERR_GET_LIB(error) == ERR_LIB_EVP) { 50 | switch (ERR_GET_REASON(error)) { 51 | case EVP_R_BUFFER_TOO_SMALL: { 52 | crt_error = AWS_ERROR_SHORT_BUFFER; 53 | goto on_error; 54 | } 55 | case EVP_R_UNSUPPORTED_ALGORITHM: { 56 | crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM; 57 | goto on_error; 58 | } 59 | } 60 | } 61 | 62 | crt_error = AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED; 63 | 64 | on_error: 65 | AWS_LOGF_ERROR( 66 | subject, 67 | "%s() failed. returned: %d extended error:%lu(%s) aws_error:%s", 68 | function_name, 69 | evp_error, 70 | (unsigned long)error, 71 | error_message == NULL ? "" : error_message, 72 | aws_error_name(crt_error)); 73 | 74 | return aws_raise_error(crt_error); 75 | } 76 | -------------------------------------------------------------------------------- /source/symmetric_cipher.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef BYO_CRYPTO 10 | 11 | extern struct aws_symmetric_cipher *aws_aes_cbc_256_new_impl( 12 | struct aws_allocator *allocator, 13 | const struct aws_byte_cursor *key, 14 | const struct aws_byte_cursor *iv); 15 | 16 | extern struct aws_symmetric_cipher *aws_aes_ctr_256_new_impl( 17 | struct aws_allocator *allocator, 18 | const struct aws_byte_cursor *key, 19 | const struct aws_byte_cursor *iv); 20 | 21 | extern struct aws_symmetric_cipher *aws_aes_gcm_256_new_impl( 22 | struct aws_allocator *allocator, 23 | const struct aws_byte_cursor *key, 24 | const struct aws_byte_cursor *iv, 25 | const struct aws_byte_cursor *aad); 26 | 27 | extern struct aws_symmetric_cipher *aws_aes_keywrap_256_new_impl( 28 | struct aws_allocator *allocator, 29 | const struct aws_byte_cursor *key); 30 | 31 | #else /* BYO_CRYPTO */ 32 | struct aws_symmetric_cipher *aws_aes_cbc_256_new_impl( 33 | struct aws_allocator *allocator, 34 | const struct aws_byte_cursor *key, 35 | const struct aws_byte_cursor *iv) { 36 | (void)allocator; 37 | (void)key; 38 | (void)iv; 39 | abort(); 40 | } 41 | 42 | struct aws_symmetric_cipher *aws_aes_ctr_256_new_impl( 43 | struct aws_allocator *allocator, 44 | const struct aws_byte_cursor *key, 45 | const struct aws_byte_cursor *iv) { 46 | (void)allocator; 47 | (void)key; 48 | (void)iv; 49 | abort(); 50 | } 51 | 52 | struct aws_symmetric_cipher *aws_aes_gcm_256_new_impl( 53 | struct aws_allocator *allocator, 54 | const struct aws_byte_cursor *key, 55 | const struct aws_byte_cursor *iv, 56 | const struct aws_byte_cursor *aad) { 57 | (void)allocator; 58 | (void)key; 59 | (void)iv; 60 | (void)aad; 61 | abort(); 62 | } 63 | 64 | struct aws_symmetric_cipher *aws_aes_keywrap_256_new_impl( 65 | struct aws_allocator *allocator, 66 | const struct aws_byte_cursor *key) { 67 | (void)allocator; 68 | (void)key; 69 | abort(); 70 | } 71 | 72 | #endif /* BYO_CRYPTO */ 73 | 74 | static aws_aes_cbc_256_new_fn *s_aes_cbc_new_fn = aws_aes_cbc_256_new_impl; 75 | static aws_aes_ctr_256_new_fn *s_aes_ctr_new_fn = aws_aes_ctr_256_new_impl; 76 | static aws_aes_gcm_256_new_fn *s_aes_gcm_new_fn = aws_aes_gcm_256_new_impl; 77 | static aws_aes_keywrap_256_new_fn *s_aes_keywrap_new_fn = aws_aes_keywrap_256_new_impl; 78 | 79 | static int s_check_input_size_limits(const struct aws_symmetric_cipher *cipher, const struct aws_byte_cursor *input) { 80 | /* libcrypto uses int, not size_t, so this is the limit. 81 | * For simplicity, enforce the same rules on all platforms. */ 82 | return input->len <= INT_MAX - cipher->block_size ? AWS_OP_SUCCESS 83 | : aws_raise_error(AWS_ERROR_CAL_BUFFER_TOO_LARGE_FOR_ALGORITHM); 84 | } 85 | 86 | static int s_validate_key_materials( 87 | const struct aws_byte_cursor *key, 88 | size_t expected_key_size, 89 | const struct aws_byte_cursor *iv, 90 | size_t expected_iv_size) { 91 | if (key && key->len != expected_key_size) { 92 | return aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM); 93 | } 94 | 95 | if (iv && iv->len != expected_iv_size) { 96 | return aws_raise_error(AWS_ERROR_CAL_INVALID_CIPHER_MATERIAL_SIZE_FOR_ALGORITHM); 97 | } 98 | 99 | return AWS_OP_SUCCESS; 100 | } 101 | 102 | struct aws_symmetric_cipher *aws_aes_cbc_256_new( 103 | struct aws_allocator *allocator, 104 | const struct aws_byte_cursor *key, 105 | const struct aws_byte_cursor *iv) { 106 | 107 | if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, iv, AWS_AES_256_CIPHER_BLOCK_SIZE) != AWS_OP_SUCCESS) { 108 | return NULL; 109 | } 110 | return s_aes_cbc_new_fn(allocator, key, iv); 111 | } 112 | 113 | struct aws_symmetric_cipher *aws_aes_ctr_256_new( 114 | struct aws_allocator *allocator, 115 | const struct aws_byte_cursor *key, 116 | const struct aws_byte_cursor *iv) { 117 | if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, iv, AWS_AES_256_CIPHER_BLOCK_SIZE) != AWS_OP_SUCCESS) { 118 | return NULL; 119 | } 120 | return s_aes_ctr_new_fn(allocator, key, iv); 121 | } 122 | 123 | struct aws_symmetric_cipher *aws_aes_gcm_256_new( 124 | struct aws_allocator *allocator, 125 | const struct aws_byte_cursor *key, 126 | const struct aws_byte_cursor *iv, 127 | const struct aws_byte_cursor *aad) { 128 | if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, iv, AWS_AES_256_CIPHER_BLOCK_SIZE - sizeof(uint32_t)) != 129 | AWS_OP_SUCCESS) { 130 | return NULL; 131 | } 132 | return s_aes_gcm_new_fn(allocator, key, iv, aad); 133 | } 134 | 135 | struct aws_symmetric_cipher *aws_aes_keywrap_256_new( 136 | struct aws_allocator *allocator, 137 | const struct aws_byte_cursor *key) { 138 | if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, NULL, 0) != AWS_OP_SUCCESS) { 139 | return NULL; 140 | } 141 | return s_aes_keywrap_new_fn(allocator, key); 142 | } 143 | 144 | void aws_symmetric_cipher_destroy(struct aws_symmetric_cipher *cipher) { 145 | if (cipher) { 146 | cipher->vtable->destroy(cipher); 147 | } 148 | } 149 | 150 | int aws_symmetric_cipher_encrypt( 151 | struct aws_symmetric_cipher *cipher, 152 | struct aws_byte_cursor to_encrypt, 153 | struct aws_byte_buf *out) { 154 | 155 | AWS_PRECONDITION(aws_byte_cursor_is_valid(&to_encrypt)); 156 | 157 | if (AWS_UNLIKELY(s_check_input_size_limits(cipher, &to_encrypt) != AWS_OP_SUCCESS)) { 158 | return AWS_OP_ERR; 159 | } 160 | 161 | if (cipher->state == AWS_SYMMETRIC_CIPHER_READY) { 162 | return cipher->vtable->encrypt(cipher, to_encrypt, out); 163 | } 164 | 165 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 166 | } 167 | 168 | int aws_symmetric_cipher_decrypt( 169 | struct aws_symmetric_cipher *cipher, 170 | struct aws_byte_cursor to_decrypt, 171 | struct aws_byte_buf *out) { 172 | 173 | AWS_PRECONDITION(aws_byte_cursor_is_valid(&to_decrypt)); 174 | 175 | if (AWS_UNLIKELY(s_check_input_size_limits(cipher, &to_decrypt) != AWS_OP_SUCCESS)) { 176 | return AWS_OP_ERR; 177 | } 178 | 179 | if (cipher->state == AWS_SYMMETRIC_CIPHER_READY) { 180 | return cipher->vtable->decrypt(cipher, to_decrypt, out); 181 | } 182 | 183 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 184 | } 185 | 186 | int aws_symmetric_cipher_finalize_encryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) { 187 | if (cipher->state == AWS_SYMMETRIC_CIPHER_READY) { 188 | int ret_val = cipher->vtable->finalize_encryption(cipher, out); 189 | if (cipher->state != AWS_SYMMETRIC_CIPHER_ERROR) { 190 | cipher->state = AWS_SYMMETRIC_CIPHER_FINALIZED; 191 | } 192 | return ret_val; 193 | } 194 | 195 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 196 | } 197 | 198 | int aws_symmetric_cipher_finalize_decryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) { 199 | if (cipher->state == AWS_SYMMETRIC_CIPHER_READY) { 200 | int ret_val = cipher->vtable->finalize_decryption(cipher, out); 201 | if (cipher->state != AWS_SYMMETRIC_CIPHER_ERROR) { 202 | cipher->state = AWS_SYMMETRIC_CIPHER_FINALIZED; 203 | } 204 | return ret_val; 205 | } 206 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 207 | } 208 | 209 | int aws_symmetric_cipher_reset(struct aws_symmetric_cipher *cipher) { 210 | int ret_val = cipher->vtable->reset(cipher); 211 | if (ret_val == AWS_OP_SUCCESS) { 212 | cipher->state = AWS_SYMMETRIC_CIPHER_READY; 213 | } 214 | 215 | return ret_val; 216 | } 217 | 218 | struct aws_byte_cursor aws_symmetric_cipher_get_tag(const struct aws_symmetric_cipher *cipher) { 219 | return aws_byte_cursor_from_buf(&cipher->tag); 220 | } 221 | 222 | void aws_symmetric_cipher_set_tag(struct aws_symmetric_cipher *cipher, struct aws_byte_cursor tag) { 223 | AWS_PRECONDITION(aws_byte_cursor_is_valid(&tag)); 224 | aws_byte_buf_clean_up_secure(&cipher->tag); 225 | aws_byte_buf_init_copy_from_cursor(&cipher->tag, cipher->allocator, tag); 226 | } 227 | 228 | struct aws_byte_cursor aws_symmetric_cipher_get_initialization_vector(const struct aws_symmetric_cipher *cipher) { 229 | return aws_byte_cursor_from_buf(&cipher->iv); 230 | } 231 | 232 | struct aws_byte_cursor aws_symmetric_cipher_get_key(const struct aws_symmetric_cipher *cipher) { 233 | return aws_byte_cursor_from_buf(&cipher->key); 234 | } 235 | 236 | bool aws_symmetric_cipher_is_good(const struct aws_symmetric_cipher *cipher) { 237 | return cipher->state == AWS_SYMMETRIC_CIPHER_READY; 238 | } 239 | 240 | enum aws_symmetric_cipher_state aws_symmetric_cipher_get_state(const struct aws_symmetric_cipher *cipher) { 241 | return cipher->state; 242 | } 243 | 244 | void aws_symmetric_cipher_generate_initialization_vector( 245 | size_t len_bytes, 246 | bool is_counter_mode, 247 | struct aws_byte_buf *out) { 248 | size_t counter_len = is_counter_mode ? sizeof(uint32_t) : 0; 249 | AWS_ASSERT(len_bytes > counter_len); 250 | size_t rand_len = len_bytes - counter_len; 251 | 252 | AWS_FATAL_ASSERT(aws_device_random_buffer_append(out, rand_len) == AWS_OP_SUCCESS); 253 | 254 | if (is_counter_mode) { 255 | /* put counter at the end, initialized to 1 */ 256 | aws_byte_buf_write_be32(out, 1); 257 | } 258 | } 259 | 260 | void aws_symmetric_cipher_generate_key(size_t key_len_bytes, struct aws_byte_buf *out) { 261 | AWS_FATAL_ASSERT(aws_device_random_buffer_append(out, key_len_bytes) == AWS_OP_SUCCESS); 262 | } 263 | 264 | int aws_symmetric_cipher_try_ensure_sufficient_buffer_space(struct aws_byte_buf *buf, size_t size) { 265 | if (buf->capacity - buf->len < size) { 266 | return aws_byte_buf_reserve_relative(buf, size); 267 | } 268 | 269 | return AWS_OP_SUCCESS; 270 | } 271 | -------------------------------------------------------------------------------- /source/unix/opensslcrypto_hash.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | static void s_destroy(struct aws_hash *hash); 12 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); 13 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); 14 | 15 | static struct aws_hash_vtable s_md5_vtable = { 16 | .destroy = s_destroy, 17 | .update = s_update, 18 | .finalize = s_finalize, 19 | .alg_name = "MD5", 20 | .provider = "OpenSSL Compatible libcrypto", 21 | }; 22 | 23 | static struct aws_hash_vtable s_sha256_vtable = { 24 | .destroy = s_destroy, 25 | .update = s_update, 26 | .finalize = s_finalize, 27 | .alg_name = "SHA256", 28 | .provider = "OpenSSL Compatible libcrypto", 29 | }; 30 | 31 | static struct aws_hash_vtable s_sha1_vtable = { 32 | .destroy = s_destroy, 33 | .update = s_update, 34 | .finalize = s_finalize, 35 | .alg_name = "SHA1", 36 | .provider = "OpenSSL Compatible libcrypto", 37 | }; 38 | 39 | static void s_destroy(struct aws_hash *hash) { 40 | if (hash == NULL) { 41 | return; 42 | } 43 | 44 | EVP_MD_CTX *ctx = hash->impl; 45 | if (ctx != NULL) { 46 | g_aws_openssl_evp_md_ctx_table->free_fn(ctx); 47 | } 48 | 49 | aws_mem_release(hash->allocator, hash); 50 | } 51 | 52 | struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) { 53 | struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); 54 | 55 | if (!hash) { 56 | return NULL; 57 | } 58 | 59 | hash->allocator = allocator; 60 | hash->vtable = &s_md5_vtable; 61 | hash->digest_size = AWS_MD5_LEN; 62 | EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); 63 | hash->impl = ctx; 64 | hash->good = true; 65 | 66 | if (!hash->impl) { 67 | s_destroy(hash); 68 | aws_raise_error(AWS_ERROR_OOM); 69 | return NULL; 70 | } 71 | 72 | if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_md5(), NULL)) { 73 | s_destroy(hash); 74 | aws_raise_error(AWS_ERROR_UNKNOWN); 75 | return NULL; 76 | } 77 | 78 | return hash; 79 | } 80 | 81 | struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) { 82 | struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); 83 | 84 | if (!hash) { 85 | return NULL; 86 | } 87 | 88 | hash->allocator = allocator; 89 | hash->vtable = &s_sha256_vtable; 90 | hash->digest_size = AWS_SHA256_LEN; 91 | EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); 92 | hash->impl = ctx; 93 | hash->good = true; 94 | 95 | if (!hash->impl) { 96 | s_destroy(hash); 97 | aws_raise_error(AWS_ERROR_OOM); 98 | return NULL; 99 | } 100 | 101 | if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha256(), NULL)) { 102 | s_destroy(hash); 103 | aws_raise_error(AWS_ERROR_UNKNOWN); 104 | return NULL; 105 | } 106 | 107 | return hash; 108 | } 109 | 110 | struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator) { 111 | struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); 112 | 113 | if (!hash) { 114 | return NULL; 115 | } 116 | 117 | hash->allocator = allocator; 118 | hash->vtable = &s_sha1_vtable; 119 | hash->digest_size = AWS_SHA1_LEN; 120 | EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); 121 | hash->impl = ctx; 122 | hash->good = true; 123 | 124 | if (!hash->impl) { 125 | s_destroy(hash); 126 | aws_raise_error(AWS_ERROR_OOM); 127 | return NULL; 128 | } 129 | 130 | if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha1(), NULL)) { 131 | s_destroy(hash); 132 | aws_raise_error(AWS_ERROR_UNKNOWN); 133 | return NULL; 134 | } 135 | 136 | return hash; 137 | } 138 | 139 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { 140 | if (!hash->good) { 141 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 142 | } 143 | 144 | EVP_MD_CTX *ctx = hash->impl; 145 | 146 | if (AWS_LIKELY(g_aws_openssl_evp_md_ctx_table->update_fn(ctx, to_hash->ptr, to_hash->len))) { 147 | return AWS_OP_SUCCESS; 148 | } 149 | 150 | hash->good = false; 151 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 152 | } 153 | 154 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { 155 | if (!hash->good) { 156 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 157 | } 158 | 159 | EVP_MD_CTX *ctx = hash->impl; 160 | 161 | size_t buffer_len = output->capacity - output->len; 162 | 163 | if (buffer_len < hash->digest_size) { 164 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 165 | } 166 | 167 | if (AWS_LIKELY(g_aws_openssl_evp_md_ctx_table->final_ex_fn( 168 | ctx, output->buffer + output->len, (unsigned int *)&buffer_len))) { 169 | output->len += hash->digest_size; 170 | hash->good = false; 171 | return AWS_OP_SUCCESS; 172 | } 173 | 174 | hash->good = false; 175 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 176 | } 177 | -------------------------------------------------------------------------------- /source/unix/opensslcrypto_hmac.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | static void s_destroy(struct aws_hmac *hmac); 12 | static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac); 13 | static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output); 14 | 15 | static struct aws_hmac_vtable s_sha256_hmac_vtable = { 16 | .destroy = s_destroy, 17 | .update = s_update, 18 | .finalize = s_finalize, 19 | .alg_name = "SHA256 HMAC", 20 | .provider = "OpenSSL Compatible libcrypto", 21 | }; 22 | 23 | static void s_destroy(struct aws_hmac *hmac) { 24 | if (hmac == NULL) { 25 | return; 26 | } 27 | 28 | HMAC_CTX *ctx = hmac->impl; 29 | if (ctx != NULL) { 30 | g_aws_openssl_hmac_ctx_table->free_fn(ctx); 31 | } 32 | 33 | aws_mem_release(hmac->allocator, hmac); 34 | } 35 | 36 | /* 37 | typedef struct hmac_ctx_st { 38 | const EVP_MD *md; 39 | EVP_MD_CTX md_ctx; 40 | EVP_MD_CTX i_ctx; 41 | EVP_MD_CTX o_ctx; 42 | unsigned int key_length; 43 | unsigned char key[HMAC_MAX_MD_CBLOCK]; 44 | } HMAC_CTX; 45 | 46 | */ 47 | 48 | #define SIZEOF_OPENSSL_HMAC_CTX 300 /* <= 288 on 64 bit systems with openssl 1.0.* */ 49 | 50 | struct aws_hmac *aws_sha256_hmac_default_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { 51 | AWS_ASSERT(secret->ptr); 52 | 53 | struct aws_hmac *hmac = aws_mem_acquire(allocator, sizeof(struct aws_hmac)); 54 | 55 | if (!hmac) { 56 | return NULL; 57 | } 58 | 59 | hmac->allocator = allocator; 60 | hmac->vtable = &s_sha256_hmac_vtable; 61 | hmac->digest_size = AWS_SHA256_HMAC_LEN; 62 | HMAC_CTX *ctx = NULL; 63 | ctx = g_aws_openssl_hmac_ctx_table->new_fn(); 64 | 65 | if (!ctx) { 66 | aws_raise_error(AWS_ERROR_OOM); 67 | aws_mem_release(allocator, hmac); 68 | return NULL; 69 | } 70 | 71 | g_aws_openssl_hmac_ctx_table->init_fn(ctx); 72 | 73 | hmac->impl = ctx; 74 | hmac->good = true; 75 | 76 | if (!g_aws_openssl_hmac_ctx_table->init_ex_fn(ctx, secret->ptr, secret->len, EVP_sha256(), NULL)) { 77 | s_destroy(hmac); 78 | aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 79 | return NULL; 80 | } 81 | 82 | return hmac; 83 | } 84 | 85 | static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac) { 86 | if (!hmac->good) { 87 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 88 | } 89 | 90 | HMAC_CTX *ctx = hmac->impl; 91 | 92 | if (AWS_LIKELY(g_aws_openssl_hmac_ctx_table->update_fn(ctx, to_hmac->ptr, to_hmac->len))) { 93 | return AWS_OP_SUCCESS; 94 | } 95 | 96 | hmac->good = false; 97 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 98 | } 99 | 100 | static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output) { 101 | if (!hmac->good) { 102 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 103 | } 104 | 105 | HMAC_CTX *ctx = hmac->impl; 106 | 107 | size_t buffer_len = output->capacity - output->len; 108 | 109 | if (buffer_len < hmac->digest_size) { 110 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 111 | } 112 | 113 | if (AWS_LIKELY( 114 | g_aws_openssl_hmac_ctx_table->final_fn(ctx, output->buffer + output->len, (unsigned int *)&buffer_len))) { 115 | hmac->good = false; 116 | output->len += hmac->digest_size; 117 | return AWS_OP_SUCCESS; 118 | } 119 | 120 | hmac->good = false; 121 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 122 | } 123 | -------------------------------------------------------------------------------- /source/windows/bcrypt_hash.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | static BCRYPT_ALG_HANDLE s_sha256_alg = NULL; 14 | static size_t s_sha256_obj_len = 0; 15 | static aws_thread_once s_sha256_once = AWS_THREAD_ONCE_STATIC_INIT; 16 | 17 | static BCRYPT_ALG_HANDLE s_sha1_alg = NULL; 18 | static size_t s_sha1_obj_len = 0; 19 | static aws_thread_once s_sha1_once = AWS_THREAD_ONCE_STATIC_INIT; 20 | 21 | static BCRYPT_ALG_HANDLE s_md5_alg = NULL; 22 | static size_t s_md5_obj_len = 0; 23 | static aws_thread_once s_md5_once = AWS_THREAD_ONCE_STATIC_INIT; 24 | 25 | static void s_destroy(struct aws_hash *hash); 26 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); 27 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); 28 | 29 | static struct aws_hash_vtable s_sha256_vtable = { 30 | .destroy = s_destroy, 31 | .update = s_update, 32 | .finalize = s_finalize, 33 | .alg_name = "SHA256", 34 | .provider = "Windows CNG", 35 | }; 36 | 37 | static struct aws_hash_vtable s_sha1_vtable = { 38 | .destroy = s_destroy, 39 | .update = s_update, 40 | .finalize = s_finalize, 41 | .alg_name = "SHA1", 42 | .provider = "Windows CNG", 43 | }; 44 | 45 | static struct aws_hash_vtable s_md5_vtable = { 46 | .destroy = s_destroy, 47 | .update = s_update, 48 | .finalize = s_finalize, 49 | .alg_name = "MD5", 50 | .provider = "Windows CNG", 51 | }; 52 | 53 | struct bcrypt_hash_handle { 54 | struct aws_hash hash; 55 | BCRYPT_HASH_HANDLE hash_handle; 56 | uint8_t *hash_obj; 57 | }; 58 | 59 | static void s_load_sha256_alg_handle(void *user_data) { 60 | (void)user_data; 61 | /* this function is incredibly slow, LET IT LEAK*/ 62 | (void)BCryptOpenAlgorithmProvider(&s_sha256_alg, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); 63 | AWS_ASSERT(s_sha256_alg); 64 | DWORD result_length = 0; 65 | (void)BCryptGetProperty( 66 | s_sha256_alg, BCRYPT_OBJECT_LENGTH, (PBYTE)&s_sha256_obj_len, sizeof(s_sha256_obj_len), &result_length, 0); 67 | } 68 | 69 | static void s_load_sha1_alg_handle(void *user_data) { 70 | (void)user_data; 71 | /* this function is incredibly slow, LET IT LEAK*/ 72 | (void)BCryptOpenAlgorithmProvider(&s_sha1_alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); 73 | AWS_ASSERT(s_sha1_alg); 74 | DWORD result_length = 0; 75 | (void)BCryptGetProperty( 76 | s_sha1_alg, BCRYPT_OBJECT_LENGTH, (PBYTE)&s_sha1_obj_len, sizeof(s_sha1_obj_len), &result_length, 0); 77 | } 78 | 79 | static void s_load_md5_alg_handle(void *user_data) { 80 | (void)user_data; 81 | /* this function is incredibly slow, LET IT LEAK*/ 82 | (void)BCryptOpenAlgorithmProvider(&s_md5_alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); 83 | AWS_ASSERT(s_md5_alg); 84 | DWORD result_length = 0; 85 | (void)BCryptGetProperty( 86 | s_md5_alg, BCRYPT_OBJECT_LENGTH, (PBYTE)&s_md5_obj_len, sizeof(s_md5_obj_len), &result_length, 0); 87 | } 88 | 89 | struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) { 90 | aws_thread_call_once(&s_sha256_once, s_load_sha256_alg_handle, NULL); 91 | 92 | struct bcrypt_hash_handle *bcrypt_hash = NULL; 93 | uint8_t *hash_obj = NULL; 94 | aws_mem_acquire_many(allocator, 2, &bcrypt_hash, sizeof(struct bcrypt_hash_handle), &hash_obj, s_sha256_obj_len); 95 | 96 | if (!bcrypt_hash) { 97 | return NULL; 98 | } 99 | 100 | AWS_ZERO_STRUCT(*bcrypt_hash); 101 | bcrypt_hash->hash.allocator = allocator; 102 | bcrypt_hash->hash.vtable = &s_sha256_vtable; 103 | bcrypt_hash->hash.impl = bcrypt_hash; 104 | bcrypt_hash->hash.digest_size = AWS_SHA256_LEN; 105 | bcrypt_hash->hash.good = true; 106 | bcrypt_hash->hash_obj = hash_obj; 107 | NTSTATUS status = BCryptCreateHash( 108 | s_sha256_alg, &bcrypt_hash->hash_handle, bcrypt_hash->hash_obj, (ULONG)s_sha256_obj_len, NULL, 0, 0); 109 | 110 | if (((NTSTATUS)status) < 0) { 111 | aws_mem_release(allocator, bcrypt_hash); 112 | return NULL; 113 | } 114 | 115 | return &bcrypt_hash->hash; 116 | } 117 | 118 | struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator) { 119 | aws_thread_call_once(&s_sha1_once, s_load_sha1_alg_handle, NULL); 120 | 121 | struct bcrypt_hash_handle *bcrypt_hash = NULL; 122 | uint8_t *hash_obj = NULL; 123 | aws_mem_acquire_many(allocator, 2, &bcrypt_hash, sizeof(struct bcrypt_hash_handle), &hash_obj, s_sha1_obj_len); 124 | 125 | if (!bcrypt_hash) { 126 | return NULL; 127 | } 128 | 129 | AWS_ZERO_STRUCT(*bcrypt_hash); 130 | bcrypt_hash->hash.allocator = allocator; 131 | bcrypt_hash->hash.vtable = &s_sha1_vtable; 132 | bcrypt_hash->hash.impl = bcrypt_hash; 133 | bcrypt_hash->hash.digest_size = AWS_SHA1_LEN; 134 | bcrypt_hash->hash.good = true; 135 | bcrypt_hash->hash_obj = hash_obj; 136 | NTSTATUS status = BCryptCreateHash( 137 | s_sha1_alg, &bcrypt_hash->hash_handle, bcrypt_hash->hash_obj, (ULONG)s_sha1_obj_len, NULL, 0, 0); 138 | 139 | if (((NTSTATUS)status) < 0) { 140 | aws_mem_release(allocator, bcrypt_hash); 141 | return NULL; 142 | } 143 | 144 | return &bcrypt_hash->hash; 145 | } 146 | 147 | struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) { 148 | aws_thread_call_once(&s_md5_once, s_load_md5_alg_handle, NULL); 149 | 150 | struct bcrypt_hash_handle *bcrypt_hash = NULL; 151 | uint8_t *hash_obj = NULL; 152 | aws_mem_acquire_many(allocator, 2, &bcrypt_hash, sizeof(struct bcrypt_hash_handle), &hash_obj, s_md5_obj_len); 153 | 154 | if (!bcrypt_hash) { 155 | return NULL; 156 | } 157 | 158 | AWS_ZERO_STRUCT(*bcrypt_hash); 159 | bcrypt_hash->hash.allocator = allocator; 160 | bcrypt_hash->hash.vtable = &s_md5_vtable; 161 | bcrypt_hash->hash.impl = bcrypt_hash; 162 | bcrypt_hash->hash.digest_size = AWS_MD5_LEN; 163 | bcrypt_hash->hash.good = true; 164 | bcrypt_hash->hash_obj = hash_obj; 165 | NTSTATUS status = 166 | BCryptCreateHash(s_md5_alg, &bcrypt_hash->hash_handle, bcrypt_hash->hash_obj, (ULONG)s_md5_obj_len, NULL, 0, 0); 167 | 168 | if (((NTSTATUS)status) < 0) { 169 | aws_mem_release(allocator, bcrypt_hash); 170 | return NULL; 171 | } 172 | 173 | return &bcrypt_hash->hash; 174 | } 175 | 176 | static void s_destroy(struct aws_hash *hash) { 177 | struct bcrypt_hash_handle *ctx = hash->impl; 178 | BCryptDestroyHash(ctx->hash_handle); 179 | aws_mem_release(hash->allocator, ctx); 180 | } 181 | 182 | static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { 183 | if (!hash->good) { 184 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 185 | } 186 | 187 | struct bcrypt_hash_handle *ctx = hash->impl; 188 | NTSTATUS status = BCryptHashData(ctx->hash_handle, to_hash->ptr, (ULONG)to_hash->len, 0); 189 | 190 | if (((NTSTATUS)status) < 0) { 191 | hash->good = false; 192 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 193 | } 194 | 195 | return AWS_OP_SUCCESS; 196 | } 197 | 198 | static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { 199 | if (!hash->good) { 200 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 201 | } 202 | 203 | struct bcrypt_hash_handle *ctx = hash->impl; 204 | 205 | size_t buffer_len = output->capacity - output->len; 206 | 207 | if (buffer_len < hash->digest_size) { 208 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 209 | } 210 | 211 | NTSTATUS status = BCryptFinishHash(ctx->hash_handle, output->buffer + output->len, (ULONG)hash->digest_size, 0); 212 | 213 | hash->good = false; 214 | if (((NTSTATUS)status) < 0) { 215 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 216 | } 217 | 218 | output->len += hash->digest_size; 219 | return AWS_OP_SUCCESS; 220 | } 221 | -------------------------------------------------------------------------------- /source/windows/bcrypt_hmac.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | static BCRYPT_ALG_HANDLE s_sha256_hmac_alg = NULL; 14 | static size_t s_sha256_hmac_obj_len = 0; 15 | 16 | static aws_thread_once s_sha256_hmac_once = AWS_THREAD_ONCE_STATIC_INIT; 17 | 18 | static void s_destroy(struct aws_hmac *hash); 19 | static int s_update(struct aws_hmac *hash, const struct aws_byte_cursor *to_hash); 20 | static int s_finalize(struct aws_hmac *hash, struct aws_byte_buf *output); 21 | 22 | static struct aws_hmac_vtable s_sha256_hmac_vtable = { 23 | .destroy = s_destroy, 24 | .update = s_update, 25 | .finalize = s_finalize, 26 | .alg_name = "SHA256 HMAC", 27 | .provider = "Windows CNG", 28 | }; 29 | 30 | struct bcrypt_hmac_handle { 31 | struct aws_hmac hmac; 32 | BCRYPT_HASH_HANDLE hash_handle; 33 | uint8_t *hash_obj; 34 | }; 35 | 36 | static void s_load_alg_handle(void *user_data) { 37 | (void)user_data; 38 | /* this function is incredibly slow, LET IT LEAK*/ 39 | BCryptOpenAlgorithmProvider( 40 | &s_sha256_hmac_alg, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); 41 | AWS_ASSERT(s_sha256_hmac_alg); 42 | DWORD result_length = 0; 43 | BCryptGetProperty( 44 | s_sha256_hmac_alg, 45 | BCRYPT_OBJECT_LENGTH, 46 | (PBYTE)&s_sha256_hmac_obj_len, 47 | sizeof(s_sha256_hmac_obj_len), 48 | &result_length, 49 | 0); 50 | } 51 | 52 | struct aws_hmac *aws_sha256_hmac_default_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { 53 | aws_thread_call_once(&s_sha256_hmac_once, s_load_alg_handle, NULL); 54 | 55 | struct bcrypt_hmac_handle *bcrypt_hmac; 56 | uint8_t *hash_obj; 57 | aws_mem_acquire_many( 58 | allocator, 2, &bcrypt_hmac, sizeof(struct bcrypt_hmac_handle), &hash_obj, s_sha256_hmac_obj_len); 59 | 60 | if (!bcrypt_hmac) { 61 | return NULL; 62 | } 63 | 64 | AWS_ZERO_STRUCT(*bcrypt_hmac); 65 | bcrypt_hmac->hmac.allocator = allocator; 66 | bcrypt_hmac->hmac.vtable = &s_sha256_hmac_vtable; 67 | bcrypt_hmac->hmac.impl = bcrypt_hmac; 68 | bcrypt_hmac->hmac.digest_size = AWS_SHA256_HMAC_LEN; 69 | bcrypt_hmac->hmac.good = true; 70 | bcrypt_hmac->hash_obj = hash_obj; 71 | NTSTATUS status = BCryptCreateHash( 72 | s_sha256_hmac_alg, 73 | &bcrypt_hmac->hash_handle, 74 | bcrypt_hmac->hash_obj, 75 | (ULONG)s_sha256_hmac_obj_len, 76 | secret->ptr, 77 | (ULONG)secret->len, 78 | 0); 79 | 80 | if (((NTSTATUS)status) < 0) { 81 | aws_mem_release(allocator, bcrypt_hmac); 82 | return NULL; 83 | } 84 | 85 | return &bcrypt_hmac->hmac; 86 | } 87 | 88 | static void s_destroy(struct aws_hmac *hmac) { 89 | struct bcrypt_hmac_handle *ctx = hmac->impl; 90 | BCryptDestroyHash(ctx->hash_handle); 91 | aws_mem_release(hmac->allocator, ctx); 92 | } 93 | 94 | static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hash) { 95 | if (!hmac->good) { 96 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 97 | } 98 | 99 | struct bcrypt_hmac_handle *ctx = hmac->impl; 100 | NTSTATUS status = BCryptHashData(ctx->hash_handle, to_hash->ptr, (ULONG)to_hash->len, 0); 101 | 102 | if (((NTSTATUS)status) < 0) { 103 | hmac->good = false; 104 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 105 | } 106 | 107 | return AWS_OP_SUCCESS; 108 | } 109 | 110 | static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output) { 111 | if (!hmac->good) { 112 | return aws_raise_error(AWS_ERROR_INVALID_STATE); 113 | } 114 | 115 | struct bcrypt_hmac_handle *ctx = hmac->impl; 116 | 117 | size_t buffer_len = output->capacity - output->len; 118 | 119 | if (buffer_len < hmac->digest_size) { 120 | return aws_raise_error(AWS_ERROR_SHORT_BUFFER); 121 | } 122 | 123 | NTSTATUS status = BCryptFinishHash(ctx->hash_handle, output->buffer + output->len, (ULONG)hmac->digest_size, 0); 124 | 125 | hmac->good = false; 126 | if (((NTSTATUS)status) < 0) { 127 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); 128 | } 129 | 130 | output->len += hmac->digest_size; 131 | return AWS_OP_SUCCESS; 132 | } 133 | -------------------------------------------------------------------------------- /source/windows/bcrypt_platform_init.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | 6 | #include 7 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 8 | # include 9 | # include 10 | #endif 11 | 12 | void aws_cal_platform_init(struct aws_allocator *allocator) { 13 | (void)allocator; 14 | } 15 | 16 | void aws_cal_platform_clean_up(void) { 17 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 18 | AWSLC_thread_local_clear(); 19 | #endif 20 | } 21 | 22 | void aws_cal_platform_thread_clean_up(void) { 23 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 24 | AWSLC_thread_local_clear(); 25 | #endif 26 | } 27 | 28 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) && defined(OPENSSL_IS_AWSLC) 29 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 30 | switch (fdwReason) { 31 | case DLL_PROCESS_DETACH: 32 | AWSLC_thread_local_shutdown(); 33 | break; 34 | } 35 | return TRUE; 36 | } 37 | #endif 38 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(AwsLibFuzzer) 2 | include(AwsTestHarness) 3 | enable_testing() 4 | 5 | file(GLOB TEST_HDRS "*.h") 6 | file(GLOB TEST_SRC "*.c") 7 | 8 | file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) 9 | 10 | add_test_case(sha256_nist_test_case_1) 11 | add_test_case(sha256_nist_test_case_2) 12 | add_test_case(sha256_nist_test_case_3) 13 | add_test_case(sha256_nist_test_case_4) 14 | add_test_case(sha256_nist_test_case_5) 15 | add_test_case(sha256_nist_test_case_5_truncated) 16 | add_test_case(sha256_nist_test_case_6) 17 | add_test_case(sha256_test_invalid_buffer) 18 | add_test_case(sha256_test_oneshot) 19 | add_test_case(sha256_test_invalid_state) 20 | add_test_case(sha256_test_extra_buffer_space) 21 | 22 | add_test_case(sha1_nist_test_case_1) 23 | add_test_case(sha1_nist_test_case_2) 24 | add_test_case(sha1_nist_test_case_3) 25 | add_test_case(sha1_nist_test_case_4) 26 | add_test_case(sha1_nist_test_case_5) 27 | add_test_case(sha1_nist_test_case_5_truncated) 28 | add_test_case(sha1_nist_test_case_6) 29 | add_test_case(sha1_test_invalid_buffer) 30 | add_test_case(sha1_test_oneshot) 31 | add_test_case(sha1_test_invalid_state) 32 | add_test_case(sha1_test_extra_buffer_space) 33 | 34 | add_test_case(md5_rfc1321_test_case_1) 35 | add_test_case(md5_rfc1321_test_case_2) 36 | add_test_case(md5_rfc1321_test_case_3) 37 | add_test_case(md5_rfc1321_test_case_4) 38 | add_test_case(md5_rfc1321_test_case_5) 39 | add_test_case(md5_rfc1321_test_case_6) 40 | add_test_case(md5_rfc1321_test_case_7) 41 | add_test_case(md5_rfc1321_test_case_7_truncated) 42 | add_test_case(md5_verify_known_collision) 43 | add_test_case(md5_invalid_buffer_size) 44 | add_test_case(md5_test_invalid_state) 45 | add_test_case(md5_test_extra_buffer_space) 46 | 47 | add_test_case(sha256_hmac_rfc4231_test_case_1) 48 | add_test_case(sha256_hmac_rfc4231_test_case_2) 49 | add_test_case(sha256_hmac_rfc4231_test_case_3) 50 | add_test_case(sha256_hmac_rfc4231_test_case_4) 51 | add_test_case(sha256_hmac_rfc4231_test_case_5) 52 | add_test_case(sha256_hmac_rfc4231_test_case_6) 53 | add_test_case(sha256_hmac_rfc4231_test_case_7) 54 | add_test_case(sha256_hmac_test_oneshot) 55 | add_test_case(sha256_hmac_test_invalid_buffer) 56 | add_test_case(sha256_hmac_test_invalid_state) 57 | add_test_case(sha256_hmac_test_extra_buffer_space) 58 | 59 | add_test_case(ecdsa_p256_test_pub_key_derivation) 60 | add_test_case(ecdsa_p384_test_pub_key_derivation) 61 | add_test_case(ecdsa_p256_test_known_signing_value) 62 | add_test_case(ecdsa_p384_test_known_signing_value) 63 | add_test_case(ecdsa_test_invalid_signature) 64 | add_test_case(ecdsa_p256_test_key_gen) 65 | add_test_case(ecdsa_p384_test_key_gen) 66 | add_test_case(ecdsa_p256_test_key_gen_export) 67 | add_test_case(ecdsa_p384_test_key_gen_export) 68 | add_test_case(ecdsa_p256_test_import_asn1_key_pair) 69 | add_test_case(ecdsa_p384_test_import_asn1_key_pair) 70 | add_test_case(ecdsa_test_import_asn1_key_pair_public_only) 71 | add_test_case(ecdsa_test_import_asn1_key_pair_invalid_fails) 72 | add_test_case(ecdsa_test_signature_format) 73 | add_test_case(ecdsa_p256_test_small_coordinate_verification) 74 | 75 | add_test_case(rsa_encryption_roundtrip_pkcs1_from_user) 76 | add_test_case(rsa_encryption_roundtrip_oaep_sha256_from_user) 77 | add_test_case(rsa_encryption_roundtrip_oaep_sha512_from_user) 78 | add_test_case(rsa_signing_roundtrip_pkcs1_sha256_from_user) 79 | add_test_case(rsa_signing_roundtrip_pss_sha256_from_user) 80 | add_test_case(rsa_signing_roundtrip_pkcs1_sha1_from_user) 81 | add_test_case(rsa_getters) 82 | add_test_case(rsa_private_pkcs1_der_parsing) 83 | add_test_case(rsa_public_pkcs1_der_parsing) 84 | add_test_case(rsa_verify_signing_pkcs1_sha256) 85 | add_test_case(rsa_verify_signing_pkcs1_sha1) 86 | add_test_case(rsa_verify_signing_pss_sha256) 87 | add_test_case(rsa_decrypt_pkcs1) 88 | add_test_case(rsa_decrypt_oaep256) 89 | add_test_case(rsa_decrypt_oaep512) 90 | add_test_case(rsa_signing_mismatch_pkcs1_sha256) 91 | add_test_case(rsa_signing_mismatch_pkcs1_sha1) 92 | add_test_case(rsa_encryption_roundtrip_pkcs15_from_user_pkcs8) 93 | 94 | add_test_case(aes_cbc_NIST_CBCGFSbox256_case_1) 95 | add_test_case(aes_cbc_NIST_CBCVarKey256_case_254) 96 | add_test_case(aes_cbc_NIST_CBCVarTxt256_case_110) 97 | add_test_case(aes_cbc_NIST_CBCMMT256_case_4) 98 | add_test_case(aes_cbc_NIST_CBCMMT256_case_9) 99 | add_test_case(aes_cbc_test_with_generated_key_iv) 100 | add_test_case(aes_cbc_validate_materials_fails) 101 | add_test_case(aes_ctr_RFC3686_Case_7) 102 | add_test_case(aes_ctr_RFC3686_Case_8) 103 | add_test_case(aes_ctr_RFC3686_Case_9) 104 | add_test_case(aes_ctr_test_with_generated_key_iv) 105 | add_test_case(aes_ctr_validate_materials_fails) 106 | add_test_case(gcm_NIST_gcmEncryptExtIV256_PTLen_128_Test_0) 107 | add_test_case(gcm_NIST_gcmEncryptExtIV256_PTLen_104_Test_3) 108 | add_test_case(gcm_NIST_gcmEncryptExtIV256_PTLen_256_Test_6) 109 | add_test_case(gcm_NIST_gcmEncryptExtIV256_PTLen_408_Test_8) 110 | add_test_case(gcm_256_KAT_1) 111 | add_test_case(gcm_256_KAT_2) 112 | add_test_case(gcm_256_KAT_3) 113 | add_test_case(gcm_test_with_generated_key_iv) 114 | add_test_case(aes_gcm_validate_materials_fails) 115 | add_test_case(aes_keywrap_RFC3394_256BitKey256CekTestVector) 116 | add_test_case(aes_keywrap_Rfc3394_256BitKey_TestIntegrityCheckFailed) 117 | add_test_case(aes_keywrap_RFC3394_256BitKeyTestBadPayload) 118 | add_test_case(aes_keywrap_RFC3394_256BitKey128BitCekTestVector) 119 | add_test_case(aes_keywrap_RFC3394_256BitKey128BitCekIntegrityCheckFailedTestVector) 120 | add_test_case(aes_keywrap_RFC3394_256BitKey128BitCekPayloadCheckFailedTestVector) 121 | add_test_case(aes_keywrap_validate_materials_fails) 122 | add_test_case(aes_test_input_too_large) 123 | add_test_case(aes_test_encrypt_empty_input) 124 | add_test_case(aes_test_empty_input_gcm_tag_corner_cases) 125 | add_test_case(aes_test_gcm_tag_corner_cases) 126 | add_test_case(aes_test_gcm_tag_large_input_corner_cases) 127 | 128 | add_test_case(der_encode_integer) 129 | add_test_case(der_encode_integer_zero) 130 | add_test_case(der_encode_boolean) 131 | add_test_case(der_encode_null) 132 | add_test_case(der_encode_bit_string) 133 | add_test_case(der_encode_octet_string) 134 | add_test_case(der_encode_sequence) 135 | add_test_case(der_encode_set) 136 | add_test_case(der_decode_negative_int) 137 | add_test_case(der_decode_positive_int) 138 | add_test_case(der_decode_zero_int) 139 | add_test_case(der_decode_bad_length) 140 | add_test_case(der_decode_zero_length_int) 141 | 142 | add_test_case(der_decode_integer) 143 | add_test_case(der_decode_integer_zero) 144 | add_test_case(der_decode_boolean) 145 | add_test_case(der_decode_null) 146 | add_test_case(der_decode_bit_string) 147 | add_test_case(der_decode_octet_string) 148 | add_test_case(der_decode_sequence) 149 | add_test_case(der_decode_set) 150 | add_test_case(der_decode_key_pair) 151 | 152 | add_test_case(ecc_key_pair_random_ref_count_test) 153 | add_test_case(ecc_key_pair_public_ref_count_test) 154 | add_test_case(ecc_key_pair_asn1_ref_count_test) 155 | add_test_case(ecc_key_pair_private_ref_count_test) 156 | add_test_case(ecc_key_gen_from_private_fuzz_test) 157 | 158 | add_test_case(ed25519_key_pair_generate_test) 159 | 160 | generate_test_driver(${PROJECT_NAME}-tests) 161 | 162 | # OpenBSD 7.4+ defaults to linking with --execute-only which is not always safe for AWS-LC. 163 | # We have similar link flags in bindings, but in this case we need on the test executable, 164 | # because ed25519 keygen is hitting the same issue 165 | # (according to aws-lc huge tables in text section for ed25519 is the likely culprit) 166 | if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") 167 | target_link_options(${PROJECT_NAME}-tests PRIVATE "-Wl,--no-execute-only") 168 | endif() 169 | -------------------------------------------------------------------------------- /tests/ed25519_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "test_case_helper.h" 11 | 12 | #if defined(AWS_OS_LINUX) 13 | # include 14 | #endif 15 | 16 | static int s_ed25519_key_pair_generate_test(struct aws_allocator *allocator, void *ctx) { 17 | (void)ctx; 18 | (void)allocator; 19 | 20 | aws_cal_library_test_init(allocator); 21 | 22 | struct aws_ed25519_key_pair *pair = aws_ed25519_key_pair_new_generate(allocator); 23 | 24 | if (pair == NULL && aws_last_error() == AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM) { 25 | #if defined(AWS_USE_LIBCRYPTO_TO_SUPPORT_ED25519_EVERYWHERE) 26 | ASSERT_TRUE(false); 27 | #endif 28 | 29 | #if defined(AWS_OS_LINUX) 30 | # if defined(OPENSSL_IS_OPENSSL) 31 | # if OPENSSL_VERSION_NUMBER >= 0x10101000L 32 | ASSERT_TRUE(false); 33 | # endif 34 | # endif 35 | #endif 36 | 37 | return AWS_OP_SKIP; 38 | } 39 | 40 | ASSERT_NOT_NULL(pair); 41 | 42 | struct aws_byte_buf buf_pub_ssh; 43 | aws_byte_buf_init( 44 | &buf_pub_ssh, allocator, aws_ed25519_key_pair_get_public_key_size(AWS_CAL_ED25519_KEY_EXPORT_OPENSSH_B64)); 45 | 46 | ASSERT_SUCCESS(aws_ed25519_key_pair_get_public_key(pair, AWS_CAL_ED25519_KEY_EXPORT_OPENSSH_B64, &buf_pub_ssh)); 47 | ASSERT_UINT_EQUALS(buf_pub_ssh.len, 68); 48 | 49 | struct aws_byte_buf buf_pub_raw; 50 | aws_byte_buf_init( 51 | &buf_pub_raw, allocator, aws_ed25519_key_pair_get_public_key_size(AWS_CAL_ED25519_KEY_EXPORT_RAW)); 52 | 53 | ASSERT_SUCCESS(aws_ed25519_key_pair_get_public_key(pair, AWS_CAL_ED25519_KEY_EXPORT_RAW, &buf_pub_raw)); 54 | ASSERT_UINT_EQUALS(buf_pub_raw.len, 32); 55 | 56 | struct aws_byte_buf buf_priv_ssh; 57 | aws_byte_buf_init( 58 | &buf_priv_ssh, allocator, aws_ed25519_key_pair_get_private_key_size(AWS_CAL_ED25519_KEY_EXPORT_OPENSSH_B64)); 59 | 60 | ASSERT_SUCCESS(aws_ed25519_key_pair_get_private_key(pair, AWS_CAL_ED25519_KEY_EXPORT_OPENSSH_B64, &buf_priv_ssh)); 61 | ASSERT_UINT_EQUALS(buf_priv_ssh.len, 312); 62 | 63 | struct aws_byte_buf buf_priv_raw; 64 | aws_byte_buf_init( 65 | &buf_priv_raw, allocator, aws_ed25519_key_pair_get_private_key_size(AWS_CAL_ED25519_KEY_EXPORT_RAW)); 66 | 67 | ASSERT_SUCCESS(aws_ed25519_key_pair_get_private_key(pair, AWS_CAL_ED25519_KEY_EXPORT_RAW, &buf_priv_raw)); 68 | ASSERT_UINT_EQUALS(buf_priv_raw.len, 32); 69 | 70 | ASSERT_NOT_NULL(pair); 71 | aws_ed25519_key_pair_release(pair); 72 | 73 | aws_byte_buf_clean_up(&buf_pub_ssh); 74 | aws_byte_buf_clean_up(&buf_priv_ssh); 75 | aws_byte_buf_clean_up(&buf_pub_raw); 76 | aws_byte_buf_clean_up(&buf_priv_raw); 77 | 78 | aws_cal_library_clean_up(); 79 | 80 | return AWS_OP_SUCCESS; 81 | } 82 | 83 | AWS_TEST_CASE(ed25519_key_pair_generate_test, s_ed25519_key_pair_generate_test) 84 | -------------------------------------------------------------------------------- /tests/sha1_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0. 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include "test_case_helper.h" 10 | /* 11 | * these are the NIST test vectors, as compiled here: 12 | * https://www.di-mgt.com.au/sha_testvectors.html 13 | */ 14 | 15 | static int s_sha1_nist_test_case_1_fn(struct aws_allocator *allocator, void *ctx) { 16 | (void)ctx; 17 | 18 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("abc"); 19 | uint8_t expected[] = { 20 | 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 21 | 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d, 22 | }; 23 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 24 | 25 | return s_verify_hash_test_case(allocator, &input, &expected_buf, aws_sha1_new); 26 | } 27 | 28 | AWS_TEST_CASE(sha1_nist_test_case_1, s_sha1_nist_test_case_1_fn) 29 | 30 | static int s_sha1_nist_test_case_2_fn(struct aws_allocator *allocator, void *ctx) { 31 | (void)ctx; 32 | 33 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str(""); 34 | uint8_t expected[] = { 35 | 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 36 | 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 37 | }; 38 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 39 | 40 | return s_verify_hash_test_case(allocator, &input, &expected_buf, aws_sha1_new); 41 | } 42 | 43 | AWS_TEST_CASE(sha1_nist_test_case_2, s_sha1_nist_test_case_2_fn) 44 | 45 | static int s_sha1_nist_test_case_3_fn(struct aws_allocator *allocator, void *ctx) { 46 | (void)ctx; 47 | 48 | struct aws_byte_cursor input = 49 | aws_byte_cursor_from_c_str("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); 50 | uint8_t expected[] = { 51 | 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, 52 | 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1, 53 | }; 54 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 55 | 56 | return s_verify_hash_test_case(allocator, &input, &expected_buf, aws_sha1_new); 57 | } 58 | 59 | AWS_TEST_CASE(sha1_nist_test_case_3, s_sha1_nist_test_case_3_fn) 60 | 61 | static int s_sha1_nist_test_case_4_fn(struct aws_allocator *allocator, void *ctx) { 62 | (void)ctx; 63 | 64 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("abcdefghbcdefghicdefghijdefghijkefghijklfghij" 65 | "klmghijklmnhijklmnoijklmnopjklmnopqklm" 66 | "nopqrlmnopqrsmnopqrstnopqrstu"); 67 | uint8_t expected[] = { 68 | 0xa4, 0x9b, 0x24, 0x46, 0xa0, 0x2c, 0x64, 0x5b, 0xf4, 0x19, 69 | 0xf9, 0x95, 0xb6, 0x70, 0x91, 0x25, 0x3a, 0x04, 0xa2, 0x59, 70 | }; 71 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 72 | 73 | return s_verify_hash_test_case(allocator, &input, &expected_buf, aws_sha1_new); 74 | } 75 | 76 | AWS_TEST_CASE(sha1_nist_test_case_4, s_sha1_nist_test_case_4_fn) 77 | 78 | static int s_sha1_nist_test_case_5_fn(struct aws_allocator *allocator, void *ctx) { 79 | (void)ctx; 80 | 81 | aws_cal_library_test_init(allocator); 82 | 83 | struct aws_hash *hash = aws_sha1_new(allocator); 84 | ASSERT_NOT_NULL(hash); 85 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("a"); 86 | 87 | for (size_t i = 0; i < 1000000; ++i) { 88 | ASSERT_SUCCESS(aws_hash_update(hash, &input)); 89 | } 90 | 91 | uint8_t output[AWS_SHA1_LEN] = {0}; 92 | struct aws_byte_buf output_buf = aws_byte_buf_from_array(output, sizeof(output)); 93 | output_buf.len = 0; 94 | ASSERT_SUCCESS(aws_hash_finalize(hash, &output_buf, 0)); 95 | 96 | uint8_t expected[] = { 97 | 0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e, 98 | 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f, 99 | }; 100 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 101 | ASSERT_BIN_ARRAYS_EQUALS(expected_buf.ptr, expected_buf.len, output_buf.buffer, output_buf.len); 102 | 103 | aws_hash_destroy(hash); 104 | 105 | aws_cal_library_clean_up(); 106 | 107 | return AWS_OP_SUCCESS; 108 | } 109 | 110 | AWS_TEST_CASE(sha1_nist_test_case_5, s_sha1_nist_test_case_5_fn) 111 | 112 | static int s_sha1_nist_test_case_5_truncated_fn(struct aws_allocator *allocator, void *ctx) { 113 | (void)ctx; 114 | 115 | aws_cal_library_test_init(allocator); 116 | 117 | struct aws_hash *hash = aws_sha1_new(allocator); 118 | ASSERT_NOT_NULL(hash); 119 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("a"); 120 | 121 | for (size_t i = 0; i < 1000000; ++i) { 122 | ASSERT_SUCCESS(aws_hash_update(hash, &input)); 123 | } 124 | 125 | uint8_t expected[] = { 126 | 0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31}; 127 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 128 | uint8_t output[AWS_SHA1_LEN] = {0}; 129 | struct aws_byte_buf output_buf = aws_byte_buf_from_array(output, expected_buf.len); 130 | output_buf.len = 0; 131 | ASSERT_SUCCESS(aws_hash_finalize(hash, &output_buf, 16)); 132 | 133 | ASSERT_BIN_ARRAYS_EQUALS(expected_buf.ptr, expected_buf.len, output_buf.buffer, output_buf.len); 134 | 135 | aws_hash_destroy(hash); 136 | 137 | aws_cal_library_clean_up(); 138 | 139 | return AWS_OP_SUCCESS; 140 | } 141 | 142 | AWS_TEST_CASE(sha1_nist_test_case_5_truncated, s_sha1_nist_test_case_5_truncated_fn) 143 | 144 | static int s_sha1_nist_test_case_6_fn(struct aws_allocator *allocator, void *ctx) { 145 | (void)ctx; 146 | 147 | aws_cal_library_test_init(allocator); 148 | 149 | struct aws_hash *hash = aws_sha1_new(allocator); 150 | ASSERT_NOT_NULL(hash); 151 | struct aws_byte_cursor input = 152 | aws_byte_cursor_from_c_str("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"); 153 | 154 | for (size_t i = 0; i < 16777216; ++i) { 155 | ASSERT_SUCCESS(aws_hash_update(hash, &input)); 156 | } 157 | 158 | uint8_t output[AWS_SHA1_LEN] = {0}; 159 | struct aws_byte_buf output_buf = aws_byte_buf_from_array(output, sizeof(output)); 160 | output_buf.len = 0; 161 | ASSERT_SUCCESS(aws_hash_finalize(hash, &output_buf, 0)); 162 | 163 | uint8_t expected[] = { 164 | 0x77, 0x89, 0xf0, 0xc9, 0xef, 0x7b, 0xfc, 0x40, 0xd9, 0x33, 165 | 0x11, 0x14, 0x3d, 0xfb, 0xe6, 0x9e, 0x20, 0x17, 0xf5, 0x92, 166 | }; 167 | 168 | struct aws_byte_cursor expected_buf = aws_byte_cursor_from_array(expected, sizeof(expected)); 169 | ASSERT_BIN_ARRAYS_EQUALS(expected_buf.ptr, expected_buf.len, output_buf.buffer, output_buf.len); 170 | 171 | aws_hash_destroy(hash); 172 | 173 | aws_cal_library_clean_up(); 174 | 175 | return AWS_OP_SUCCESS; 176 | } 177 | 178 | AWS_TEST_CASE(sha1_nist_test_case_6, s_sha1_nist_test_case_6_fn) 179 | 180 | static int s_sha1_test_invalid_buffer_fn(struct aws_allocator *allocator, void *ctx) { 181 | (void)ctx; 182 | 183 | aws_cal_library_test_init(allocator); 184 | 185 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("abcdefghbcdefghicdefghijdefghijkefghijklfghij" 186 | "klmghijklmnhijklmnoijklmnopjklmnopqklm" 187 | "nopqrlmnopqrsmnopqrstnopqrstu"); 188 | uint8_t output[AWS_SHA1_LEN] = {0}; 189 | struct aws_byte_buf output_buf = aws_byte_buf_from_array(output, sizeof(output)); 190 | output_buf.len = 1; 191 | 192 | ASSERT_ERROR(AWS_ERROR_SHORT_BUFFER, aws_sha1_compute(allocator, &input, &output_buf, 0)); 193 | 194 | aws_cal_library_clean_up(); 195 | 196 | return AWS_OP_SUCCESS; 197 | } 198 | 199 | AWS_TEST_CASE(sha1_test_invalid_buffer, s_sha1_test_invalid_buffer_fn) 200 | 201 | static int s_sha1_test_oneshot_fn(struct aws_allocator *allocator, void *ctx) { 202 | (void)ctx; 203 | 204 | aws_cal_library_test_init(allocator); 205 | 206 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("abcdefghbcdefghicdefghijdefghijkefghijklfghij" 207 | "klmghijklmnhijklmnoijklmnopjklmnopqklm" 208 | "nopqrlmnopqrsmnopqrstnopqrstu"); 209 | uint8_t expected[] = { 210 | 0xa4, 0x9b, 0x24, 0x46, 0xa0, 0x2c, 0x64, 0x5b, 0xf4, 0x19, 211 | 0xf9, 0x95, 0xb6, 0x70, 0x91, 0x25, 0x3a, 0x04, 0xa2, 0x59, 212 | }; 213 | 214 | uint8_t output[AWS_SHA1_LEN] = {0}; 215 | struct aws_byte_buf output_buf = aws_byte_buf_from_array(output, sizeof(output)); 216 | output_buf.len = 0; 217 | 218 | ASSERT_SUCCESS(aws_sha1_compute(allocator, &input, &output_buf, 0)); 219 | ASSERT_BIN_ARRAYS_EQUALS(expected, sizeof(expected), output_buf.buffer, output_buf.len); 220 | 221 | aws_cal_library_clean_up(); 222 | 223 | return AWS_OP_SUCCESS; 224 | } 225 | 226 | AWS_TEST_CASE(sha1_test_oneshot, s_sha1_test_oneshot_fn) 227 | 228 | static int s_sha1_test_invalid_state_fn(struct aws_allocator *allocator, void *ctx) { 229 | (void)ctx; 230 | 231 | aws_cal_library_test_init(allocator); 232 | 233 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("abcdefghbcdefghicdefghijdefghijkefghijklfghij" 234 | "klmghijklmnhijklmnoijklmnopjklmnopqklm" 235 | "nopqrlmnopqrsmnopqrstnopqrstu"); 236 | 237 | struct aws_hash *hash = aws_sha1_new(allocator); 238 | ASSERT_NOT_NULL(hash); 239 | 240 | uint8_t output[AWS_SHA1_LEN] = {0}; 241 | struct aws_byte_buf output_buf = aws_byte_buf_from_array(output, sizeof(output)); 242 | output_buf.len = 0; 243 | 244 | ASSERT_SUCCESS(aws_hash_update(hash, &input)); 245 | ASSERT_SUCCESS(aws_hash_finalize(hash, &output_buf, 0)); 246 | ASSERT_ERROR(AWS_ERROR_INVALID_STATE, aws_hash_update(hash, &input)); 247 | ASSERT_ERROR(AWS_ERROR_INVALID_STATE, aws_hash_finalize(hash, &output_buf, 0)); 248 | 249 | aws_hash_destroy(hash); 250 | 251 | aws_cal_library_clean_up(); 252 | 253 | return AWS_OP_SUCCESS; 254 | } 255 | AWS_TEST_CASE(sha1_test_invalid_state, s_sha1_test_invalid_state_fn) 256 | 257 | static int s_sha1_test_extra_buffer_space_fn(struct aws_allocator *allocator, void *ctx) { 258 | (void)ctx; 259 | 260 | aws_cal_library_test_init(allocator); 261 | 262 | struct aws_byte_cursor input = aws_byte_cursor_from_c_str("123456789012345678901234567890123456789012345" 263 | "67890123456789012345678901234567890"); 264 | 265 | struct aws_byte_buf digest_size_buf; 266 | struct aws_byte_buf super_size_buf; 267 | 268 | aws_byte_buf_init(&digest_size_buf, allocator, AWS_SHA1_LEN); 269 | aws_byte_buf_init(&super_size_buf, allocator, AWS_SHA1_LEN + 100); 270 | 271 | aws_sha1_compute(allocator, &input, &digest_size_buf, 0); 272 | aws_sha1_compute(allocator, &input, &super_size_buf, 0); 273 | 274 | ASSERT_TRUE(aws_byte_buf_eq(&digest_size_buf, &super_size_buf)); 275 | ASSERT_TRUE(super_size_buf.len == AWS_SHA1_LEN); 276 | 277 | aws_byte_buf_clean_up(&digest_size_buf); 278 | aws_byte_buf_clean_up(&super_size_buf); 279 | 280 | aws_cal_library_clean_up(); 281 | 282 | return AWS_OP_SUCCESS; 283 | } 284 | AWS_TEST_CASE(sha1_test_extra_buffer_space, s_sha1_test_extra_buffer_space_fn) 285 | -------------------------------------------------------------------------------- /tests/test_case_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef AWS_CAL_TEST_CASE_HELPER_H 2 | #define AWS_CAL_TEST_CASE_HELPER_H 3 | /** 4 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * SPDX-License-Identifier: Apache-2.0. 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #if !defined(BYO_CRYPTO) && !defined(AWS_OS_APPLE) && !defined(AWS_OS_WINDOWS) 14 | # include 15 | #endif 16 | 17 | /** 18 | * If $AWS_TEST_FIPS env-var is set, turn on FIPS mode. 19 | * Then do normal aws_cal_library_init() 20 | */ 21 | static inline void aws_cal_library_test_init(struct aws_allocator *allocator) { 22 | struct aws_string *key_AWS_TEST_FIPS = aws_string_new_from_c_str(allocator, "AWS_TEST_FIPS"); 23 | struct aws_string *val_AWS_TEST_FIPS = NULL; 24 | aws_get_environment_value(allocator, key_AWS_TEST_FIPS, &val_AWS_TEST_FIPS); 25 | bool is_fips_desired = val_AWS_TEST_FIPS != NULL; 26 | aws_string_destroy(key_AWS_TEST_FIPS); 27 | aws_string_destroy(val_AWS_TEST_FIPS); 28 | 29 | if (is_fips_desired) { 30 | #if defined(OPENSSL_IS_AWSLC) 31 | AWS_FATAL_ASSERT(FIPS_mode_set(1) == 1 && "FIPS_mode_set(1) must succeed"); 32 | #else 33 | AWS_FATAL_ASSERT(!is_fips_desired && "AWS_TEST_FIPS is currently only supported with AWS-LC"); 34 | #endif 35 | } 36 | 37 | aws_cal_library_init(allocator); 38 | } 39 | 40 | static inline int s_verify_hmac_test_case( 41 | struct aws_allocator *allocator, 42 | struct aws_byte_cursor *input, 43 | struct aws_byte_cursor *secret, 44 | struct aws_byte_cursor *expected, 45 | aws_hmac_new_fn *new_fn) { 46 | 47 | aws_cal_library_test_init(allocator); 48 | 49 | /* test all possible segmentation lengths from 1 byte at a time to the entire 50 | * input. Using a do-while so that we still do 1 pass on 0-length input */ 51 | size_t advance_i = 1; 52 | do { 53 | uint8_t output[128] = {0}; 54 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output, AWS_ARRAY_SIZE(output)); 55 | 56 | struct aws_hmac *hmac = new_fn(allocator, secret); 57 | ASSERT_NOT_NULL(hmac); 58 | 59 | struct aws_byte_cursor input_cpy = *input; 60 | 61 | while (input_cpy.len) { 62 | size_t max_advance = aws_min_size(input_cpy.len, advance_i); 63 | struct aws_byte_cursor segment = aws_byte_cursor_from_array(input_cpy.ptr, max_advance); 64 | ASSERT_SUCCESS(aws_hmac_update(hmac, &segment)); 65 | aws_byte_cursor_advance(&input_cpy, max_advance); 66 | } 67 | 68 | size_t truncation_size = expected->len; 69 | 70 | ASSERT_SUCCESS(aws_hmac_finalize(hmac, &output_buf, truncation_size)); 71 | ASSERT_BIN_ARRAYS_EQUALS(expected->ptr, expected->len, output_buf.buffer, output_buf.len); 72 | 73 | aws_hmac_destroy(hmac); 74 | } while (++advance_i <= input->len); 75 | 76 | aws_cal_library_clean_up(); 77 | 78 | return AWS_OP_SUCCESS; 79 | } 80 | 81 | static inline int s_verify_hash_test_case( 82 | struct aws_allocator *allocator, 83 | struct aws_byte_cursor *input, 84 | struct aws_byte_cursor *expected, 85 | aws_hash_new_fn *new_fn) { 86 | 87 | aws_cal_library_test_init(allocator); 88 | 89 | /* test all possible segmentation lengths from 1 byte at a time to the entire 90 | * input. Using a do-while so that we still do 1 pass on 0-length input */ 91 | size_t advance_i = 1; 92 | do { 93 | uint8_t output[128] = {0}; 94 | struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output, AWS_ARRAY_SIZE(output)); 95 | 96 | struct aws_hash *hash = new_fn(allocator); 97 | ASSERT_NOT_NULL(hash); 98 | 99 | struct aws_byte_cursor input_cpy = *input; 100 | 101 | while (input_cpy.len) { 102 | size_t max_advance = aws_min_size(input_cpy.len, advance_i); 103 | struct aws_byte_cursor segment = aws_byte_cursor_from_array(input_cpy.ptr, max_advance); 104 | ASSERT_SUCCESS(aws_hash_update(hash, &segment)); 105 | aws_byte_cursor_advance(&input_cpy, max_advance); 106 | } 107 | 108 | size_t truncation_size = expected->len; 109 | 110 | ASSERT_SUCCESS(aws_hash_finalize(hash, &output_buf, truncation_size)); 111 | ASSERT_BIN_ARRAYS_EQUALS(expected->ptr, expected->len, output_buf.buffer, output_buf.len); 112 | 113 | aws_hash_destroy(hash); 114 | } while (++advance_i <= input->len); 115 | 116 | aws_cal_library_clean_up(); 117 | 118 | return AWS_OP_SUCCESS; 119 | } 120 | 121 | #endif /*AWS_CAL_TEST_CASE_HELPER_H*/ 122 | --------------------------------------------------------------------------------