Skip to content

Commit

Permalink
Review pass one
Browse files Browse the repository at this point in the history
  • Loading branch information
pennyannn committed Dec 4, 2023
1 parent 8de78d9 commit 0d2904c
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 28 deletions.
8 changes: 7 additions & 1 deletion NSym/spec/SHA384recEquiv.cry
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ property processBlock_Common_equiv (H : [8*w]) (Mi : [16][w]) =
join (SHA384::processBlock_Common (split H) Mi) == SHA384rec::processBlock_Common_rec H w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15
where [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15] = Mi

// The function processBlocks is a recursive/loop structure over processBlock_Common.
// Likewise, the function processBlocks_rec is a recursive structure over
// processBlock_Common_rec.
// Having verified the equivalence between processBlock_Common and
// processBlock_Common_rec, we then state the lemma for the top-level loop strucures.
// Manual inspection is only required for the loop structure.

// This property could not be proved nor checked due to Cryptol's lack of support for loops and Arrays
// Manual inspection is required
property processBlocks_equiv (H : [8*w]) (data : ByteArray) (data2 : WordArray) (n : [64]) =
// This lemma lacks a hypothesis about the equivalence between data and data2
// This hypothesis requires quantifiers
Expand Down
8 changes: 7 additions & 1 deletion NSym/spec/SHA512recEquiv.cry
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ property processBlock_Common_equiv (H : [8*w]) (Mi : [16][w]) =
join (SHA512::processBlock_Common (split H) Mi) == SHA512rec::processBlock_Common_rec H w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15
where [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15] = Mi

// The function processBlocks is a recursive/loop structure over processBlock_Common.
// Likewise, the function processBlocks_rec is a recursive structure over
// processBlock_Common_rec.
// Having verified the equivalence between processBlock_Common and
// processBlock_Common_rec, we then state the lemma for the top-level loop strucures.
// Manual inspection is only required for the loop structures.

// This property could not be proved nor checked due to Cryptol's lack of support for loops and Arrays
// Manual inspection is required
property processBlocks_equiv (H : [8*w]) (data : ByteArray) (data2 : WordArray) (n : [64]) =
// This lemma lacks a hypothesis about the equivalence between data and data2
// This hypothesis requires quantifiers
Expand Down
39 changes: 20 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

This repository contains specifications, proof scripts, and other artifacts required to formally verify portions of [AWS libcrypto](https://github.com/awslabs/aws-lc). Formal verification is used to locate bugs and increase assurance of the correctness and security of the library.

C and X86_64 proofs are carried out in [SAW](https://saw.galois.com/) using [Cryptol](https://cryptol.net/) specifications stored in the [Galois Cryptol spec repository](https://github.com/GaloisInc/cryptol-specs). AArch64 proofs are carried out in NSym using translated specifications from Cryptol. [Coq](https://coq.inria.fr) proofs are developed for proving properties of some of the Cryptol specifications.
C and X86_64 proofs are carried out in [SAW](https://saw.galois.com/) using [Cryptol](https://cryptol.net/) specifications stored in the [Galois Cryptol spec repository](https://github.com/GaloisInc/cryptol-specs). AArch64 proofs are carried out in NSym (a tool for symbolically-simulating and verifying Arm machine code that is currently under development by AWS) using translated specifications from Cryptol. [Coq](https://coq.inria.fr) proofs are developed for proving properties of some of the Cryptol specifications.

## Building and Running
The easiest way to build the library and run the proofs is to use [Docker](https://docs.docker.com/get-docker/). To check the proofs, execute the following steps in the top-level directory of the repository.
Expand Down Expand Up @@ -35,23 +35,23 @@ AWS libcrypto includes many cryptographic algorithm implementations for several

| Algorithm | Variants | API Operations | Platform | Caveats | Tech |
| ----------| -------------| --------------- | -----------| ------------ | --------- |
| SHA-2 | 384, 512 | EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal | SandyBridge+ | NoEngine, MemCorrect | [SAW](SPEC.md) |
| SHA-2 | 384 | EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal | neoverse-n1, neoverse-v1 | NoEngine, MemCorrect, ArmSpecGap | [SAW](SPEC.md) |
| HMAC | with <nobr>SHA-384</nobr> | HMAC_CTX_init, HMAC_Init_ex, HMAC_Update, HMAC_Final, HMAC | SandyBridge+ | NoEngine, MemCorrect, InitZero, NoInline, CRYPTO_once_Correct | [SAW](SPEC.md) |
| <nobr>AES-KW(P)</nobr> | 256 | AES_wrap_key, AES_unwrap_key, AES_wrap_key_padded, AES_unwrap_key_padded | SandyBridge+ | InputLength, MemCorrect, NoInline |[SAW](SPEC.md) |
| Elliptic Curve Keys and Parameters | with <nobr>P-384</nobr> | EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new, EVP_PKEY_paramgen_init, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_paramgen, EVP_PKEY_keygen_init, EVP_PKEY_keygen | SandyBridge+ | EC_Ops_Correct, NoEngine, MemCorrect, CRYPTO_refcount_Correct, CRYPTO_once_Correct, OptNone, SAWBreakpoint |[SAW](SPEC.md) |
| ECDSA | with <nobr>P-384</nobr>, <nobr>SHA-384</nobr> | EVP_DigestSignInit, EVP_DigestVerifyInit, EVP_DigestSignUpdate, EVP_DigestVerifyUpdate, EVP_DigestSignFinal, EVP_DigestVerifyFinal, EVP_DigestSign, EVP_DigestVerify | SandyBridge+ | EC_Ops_Correct, NoEngine, MemCorrect, ECDSA_k_Valid, ECDSA_SignatureLength, CRYPTO_refcount_Correct, CRYPTO_once_Correct, ERR_put_error_Correct, NoInline |[SAW](SPEC.md) |
| ECDH | with <nobr>P-384</nobr> | EVP_PKEY_derive_init, EVP_PKEY_derive | SandyBridge+ | EC_Ops_Correct, MemCorrect, NoEngine, CRYPTO_refcount_Correct, PubKeyValid |[SAW](SPEC.md) |
| HKDF | with <nobr>HMAC-SHA384</nobr> | HKDF_extract, HKDF_expand, HKDF | SandyBridge+ | MemCorrect, NoEngine, NoInline, OutputLength, CRYPTO_once_Correct |[SAW](SPEC.md) |

The platforms for which code is verified are defined in the following table. In all cases, the actual verification is performed on code that is produced by Clang 14 (for cross-compilation to AArch64) and Clang 10, but the verification results also apply to any compiler that produces semantically equivalent code.

| Platform | Description |
| --------------- | ------------|
| SandyBridge+ | x86-64 with AES-NI, CLMUL, and AVX. Compile switches: see [build_llvm.sh](SAW/scripts/x86_64/build_llvm.sh) and [build_x86.sh](SAW/scripts/x86_64/build_x86.sh)
| SandyBridge-Skylake | x86-64 with AES-NI, CLMUL, and AVX, but not AVX-512. Compile switches: see [build_llvm.sh](SAW/scripts/x86_64/build_llvm.sh) and [build_x86.sh](SAW/scripts/x86_64/build_x86.sh)
| neoverse-n1 | aarch64 without SHA512. Compile switches: see [build_llvm.sh](SAW/scripts/aarch64/build_llvm.sh) and [build_aarch64.sh](NSym/scripts/build_aarch64.sh)
| neoverse-v1 | aarch64 with SHA512. Compile switches: see [build_llvm.sh](SAW/scripts/aarch64/build_llvm.sh) and [build_aarch64.sh](NSym/scripts/build_aarch64.sh)
| [SHA-2](SPEC.md#SHA-2) | 384, 512 | EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal | SandyBridge+ | NoEngine, MemCorrect | SAW |
| [SHA-2](SPEC.md#SHA-2) | 384 | EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal | neoverse-n1, neoverse-v1 | NoEngine, MemCorrect, ArmSpecGap, SAWNSymGap | NSym |
| [HMAC](SPEC.md#HMAC-with-SHA-384) | with <nobr>SHA-384</nobr> | HMAC_CTX_init, HMAC_Init_ex, HMAC_Update, HMAC_Final, HMAC | SandyBridge+ | NoEngine, MemCorrect, InitZero, NoInline, CRYPTO_once_Correct | SAW |
| [<nobr>AES-KW(P)</nobr>](SPEC.md#AES-KWP) | 256 | AES_wrap_key, AES_unwrap_key, AES_wrap_key_padded, AES_unwrap_key_padded | SandyBridge+ | InputLength, MemCorrect, NoInline | SAW |
| [Elliptic Curve Keys and Parameters](SPEC.md#Elliptic-Curve-Keys-and-Parameters) | with <nobr>P-384</nobr> | EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new, EVP_PKEY_paramgen_init, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_paramgen, EVP_PKEY_keygen_init, EVP_PKEY_keygen | SandyBridge+ | EC_Ops_Correct, NoEngine, MemCorrect, CRYPTO_refcount_Correct, CRYPTO_once_Correct, OptNone, SAWBreakpoint | SAW |
| [ECDSA](SPEC.md#ECDSA) | with <nobr>P-384</nobr>, <nobr>SHA-384</nobr> | EVP_DigestSignInit, EVP_DigestVerifyInit, EVP_DigestSignUpdate, EVP_DigestVerifyUpdate, EVP_DigestSignFinal, EVP_DigestVerifyFinal, EVP_DigestSign, EVP_DigestVerify | SandyBridge+ | EC_Ops_Correct, NoEngine, MemCorrect, ECDSA_k_Valid, ECDSA_SignatureLength, CRYPTO_refcount_Correct, CRYPTO_once_Correct, ERR_put_error_Correct, NoInline | SAW |
| [ECDH](SPEC.md#ECDH) | with <nobr>P-384</nobr> | EVP_PKEY_derive_init, EVP_PKEY_derive | SandyBridge+ | EC_Ops_Correct, MemCorrect, NoEngine, CRYPTO_refcount_Correct, PubKeyValid | SAW |
| [HKDF](SPEC.md#HKDF-with-HMAC-SHA384) | with <nobr>HMAC-SHA384</nobr> | HKDF_extract, HKDF_expand, HKDF | SandyBridge+ | MemCorrect, NoEngine, NoInline, OutputLength, CRYPTO_once_Correct | SAW |

The platforms for which code is verified are defined in the following table. In all cases, the actual verification is performed on code that is produced by Clang, but the verification results also apply to any compiler that produces semantically equivalent code.

| Platform | Description | Compiler |
| --------------- | ------------| -------- |
| SandyBridge+ | x86-64 with AES-NI, CLMUL, and AVX. | Clang 10. Compile switches: see [build_llvm.sh](SAW/scripts/x86_64/build_llvm.sh) and [build_x86.sh](SAW/scripts/x86_64/build_x86.sh)
| SandyBridge-Skylake | x86-64 with AES-NI, CLMUL, and AVX, but not AVX-512. | Clang 10. Compile switches: see [build_llvm.sh](SAW/scripts/x86_64/build_llvm.sh) and [build_x86.sh](SAW/scripts/x86_64/build_x86.sh)
| neoverse-n1 | aarch64 without SHA512. | Clang 10 for C and Clang 14 for assembly. Compile switches: see [build_llvm.sh](SAW/scripts/aarch64/build_llvm.sh) and [build_aarch64.sh](NSym/scripts/build_aarch64.sh)
| neoverse-v1 | aarch64 with SHA512. | Clang 10 for C and Clang 14 for assembly. Compile switches: see [build_llvm.sh](SAW/scripts/aarch64/build_llvm.sh) and [build_aarch64.sh](NSym/scripts/build_aarch64.sh)

The caveats associated with some of the verification results are defined in the table below.

Expand All @@ -72,7 +72,8 @@ The caveats associated with some of the verification results are defined in the
| OptNone | The implementation is verified correct assuming that certain functions are not optimized by the compiler. |
| PubKeyValid | Public key validity checks are not verified, and the code is only proved correct for the public keys that pass these checks. |
| SAWBreakpoint | The proof uses SAW's breakpoint feature. This feature assumes the specification on the breakpoint function for the inductive hypothesis. The feature lacks well-foundedness check for the inductive invariant. |
| ArmSpecGap | The Cryptol specification used in NSym proofs for Arm is different from the one used in the corresponding SAW proofs. Specifically, recursive comprehensions are written as recursions. |
| ArmSpecGap | The Cryptol specification used in NSym proofs for Arm is different from the one used in the corresponding SAW proofs. Specifically, recursive comprehensions are written as recursions. We verify the body of the recursions are equivalent but the top-level loop structure is not verified. |
| SAWNSymGap | Proofs are conducted using SAW for C and NSym for Arm assembly. In SAW, assembly specifications are assumed when used as overrides in C proofs. We don't verify that C parameters will be passed into correct registers or stack locations.

### Functions with compiler optimization disabled

Expand Down
7 changes: 4 additions & 3 deletions SAW/proof/SHA512/SHA512-common.saw
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ enable_experimental;
// Disable debug intrinsics to avoid https://github.com/GaloisInc/crucible/issues/778
disable_debug_intrinsics;

// Load LLVM bytecode
// Print the target architecture being verified, either X86_64 or AARCH64
print (str_concat "ARCH: " (show ARCH));
include "../common/asm_helpers.saw";
// Load LLVM bytecode
m <- load_module;

// Include SHA512 common specifications
Expand All @@ -31,7 +32,7 @@ EVP_MD_pctx_ops_ov <- llvm_unsafe_assume_spec

enable_what4_hash_consing;

sha512_block_data_order_ov <- llvm_verify_asm m "../../build/x86/crypto/crypto_test" "sha512_block_data_order"
sha512_block_data_order_ov <- llvm_verify_or_assume_asm m "../../build/x86/crypto/crypto_test" "sha512_block_data_order"
[ ("K512", 5120) // Initializes the global for round constants, called K, at a size of 5120 bytes
]
true
Expand All @@ -51,7 +52,7 @@ sha512_block_data_order_ov <- llvm_verify_asm m "../../build/x86/crypto/crypto_t
enable_what4_eval;
enable_x86_what4_hash_consing;

sha512_block_data_order_array_ov <- llvm_verify_fixpoint_asm m "../../build/x86/crypto/crypto_test" "sha512_block_data_order"
sha512_block_data_order_array_ov <- llvm_verify_or_assume_fixpoint_asm m "../../build/x86/crypto/crypto_test" "sha512_block_data_order"
[ ("K512", 5120) // Initializes the global for round constants, called K, at a size of 5120 bytes
]
true
Expand Down
2 changes: 1 addition & 1 deletion SAW/proof/SHA512/aarch64-neoverse-n1.saw
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// Name of the OPENSSL machine cap variable
let cap_sym = "OPENSSL_armcap_P";
// Set machine cap value
// The value is gotten through printing OPENSSL_armcap_P in AWS-LC on Graviton3
// The value is acquired by printing OPENSSL_armcap_P in AWS-LC on Graviton3
let {{ machine_cap = 0x0000003D : [32] }};
// Set the architecture variable for controlling proof settings
let ARCH = "AARCH64";
2 changes: 1 addition & 1 deletion SAW/proof/SHA512/aarch64-neoverse-v1.saw
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// Name of the OPENSSL machine cap variable
let cap_sym = "OPENSSL_armcap_P";
// Set machine cap value
// The value is gotten through printing OPENSSL_armcap_P in AWS-LC on Graviton3
// The value is acquired by printing OPENSSL_armcap_P in AWS-LC on Graviton3
let {{ machine_cap = 0x0000187D : [32] }};
// Set the architecture variable for controlling proof settings
let ARCH = "AARCH64";
4 changes: 2 additions & 2 deletions SAW/proof/common/asm_helpers.saw
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ let load_module = if asm_switch
then llvm_load_module "../../build/llvm_x86/crypto/crypto_test.bc"
else llvm_load_module "../../build/llvm_aarch64/crypto/crypto_test.bc";

let llvm_verify_asm m bin func globals pathsat spec tactic =
let llvm_verify_or_assume_asm m bin func globals pathsat spec tactic =
if asm_switch
then llvm_verify_x86 m bin func globals pathsat spec tactic
else crucible_llvm_unsafe_assume_spec m func spec;

let llvm_verify_fixpoint_asm m bin func globals pathsat loop spec tactic =
let llvm_verify_or_assume_fixpoint_asm m bin func globals pathsat loop spec tactic =
if asm_switch
then llvm_verify_fixpoint_x86 m bin func globals pathsat loop spec tactic
else crucible_llvm_unsafe_assume_spec m func spec;

0 comments on commit 0d2904c

Please sign in to comment.