struct item* deserialize(char* buffer, int size) /*@ requires [?f0]world(?pub, ?key_clsfy) &*& [?f1]chars(buffer, size, ?cs); @*/ /*@ ensures [f0]world(pub, key_clsfy) &*& [f1]chars(buffer, size, cs) &*& item(result, ?i, pub) &*& [_]pub(i); @*/ { if (size <= MINIMAL_STRING_SIZE) abort_crypto_lib("Found corrupted item during deserialization"); struct item* item = malloc(sizeof(struct item)); if (item == 0){abort_crypto_lib("malloc of item failed");} //@ open [f0]world(pub, key_clsfy); //@ public_chars(buffer, size); //@ close [f0]world(pub, key_clsfy); item->size = size; item->content = malloc_wrapper(item->size); //@ assert item->content |-> ?cont; //@ chars_to_crypto_chars(buffer, size); //@ assert [f1]crypto_chars(normal, buffer, size, ?ccs); memcpy(item->content, buffer, (unsigned int) size); //@ get_forall_t<char>(); //@ get_forall_t<list<char> >(); parse_item(buffer, size); //@ retreive_proof_obligations(); //@ deserialize_item(ccs); //@ leak proof_obligations(pub); //@ assert [_]item_constraints(?i, ccs, pub) &*& [_]pub(i); //@ cs_to_ccs_crypto_chars(cont, cs); //@ cs_to_ccs_crypto_chars(buffer, cs); //@ chars_to_secret_crypto_chars(cont, size); //@ close item(item, i, pub); return item; }
struct item *create_hash(struct item *payload) /*@ requires [?f0]world(?pub, ?key_clsfy) &*& [?f1]item(payload, ?pay, pub); @*/ /*@ ensures [f0]world(pub, key_clsfy) &*& [f1]item(payload, pay, pub) &*& item(result, ?hash, pub) &*& col || hash == hash_item(some(pay)); @*/ { //@ open [f1]item(payload, pay, pub); //@ open [_]item_constraints(pay, ?pay_cs, pub); //@ assert [f1]payload->content |-> ?p_cont &*& [f1]payload->size |-> ?p_size; struct item* hash = malloc(sizeof(struct item)); if (hash == 0){abort_crypto_lib("malloc of item failed");} hash->size = TAG_LENGTH + HASH_SIZE; hash->content = malloc_wrapper(hash->size); write_tag(hash->content, TAG_HASH); if (payload->size < MINIMAL_STRING_SIZE) {abort_crypto_lib("Payload of hash was to small");} sha512(payload->content, (unsigned int) payload->size, hash->content + TAG_LENGTH, 0); //@ open [f0]world(pub, key_clsfy); //@ assert hash->content |-> ?cont &*& hash->size |-> ?size; //@ public_chars(cont, TAG_LENGTH); //@ assert chars(cont, TAG_LENGTH, ?cs_tag); //@ assert cs_tag == full_tag(TAG_HASH); //@ open cryptogram(cont + TAG_LENGTH, HASH_SIZE, ?cs_cont, ?h_cg); //@ assert h_cg == cg_hash(pay_cs); //@ item h = hash_item(some(pay)); //@ close ic_cg(h)(cs_cont, h_cg); //@ list<char> cs = append(cs_tag, cs_cont); //@ if (col) public_chars(cont + TAG_LENGTH, HASH_SIZE); //@ if (col) public_generated_join(polarssl_pub(pub), cs_tag, cs_cont); //@ if (col) chars_to_secret_crypto_chars(cont + TAG_LENGTH, HASH_SIZE); //@ chars_to_secret_crypto_chars(cont, TAG_LENGTH); //@ crypto_chars_join(cont); //@ close [f0]world(pub, key_clsfy); //@ close ic_parts(h)(cs_tag, cs_cont); //@ WELL_FORMED(cs_tag, cs_cont, TAG_HASH) //@ close well_formed_item_chars(h)(pay_cs); //@ leak well_formed_item_chars(h)(pay_cs); //@ close item_constraints(h, cs, pub); //@ leak item_constraints(h, cs, pub); //@ close item(hash, h, pub); return hash; //@ close [f1]item(payload, pay, pub); }
void check_is_hash(struct item *item) //@ requires [?f]world(?pub, ?key_clsfy) &*& item(item, ?i, pub); //@ ensures [f]world(pub, key_clsfy) &*& item(item, i, pub) &*& i == hash_item(_); { if (!is_hash(item)) abort_crypto_lib("Presented item is not a hash"); }
void send_data(struct network_status *net_stat) /*@ requires [?f0]world(?pub, ?key_clsfy) &*& proof_obligations(pub) &*& network_status(net_stat) &*& principal(?principal, ?count1) &*& true == bad(principal); @*/ /*@ ensures [f0]world(pub, key_clsfy) &*& proof_obligations(pub) &*& network_status(net_stat) &*& principal(principal, ?count2); @*/ { int data_size = random_int_(); if (data_size > MIN_RANDOM_SIZE) { char* data = malloc((int) data_size); if (data == 0) abort_crypto_lib("malloc failed"); random_buffer_(data, data_size); struct item *item = create_data_item(data, data_size); //@ assert item(item, ?i, pub) &*& i == data_item(?d); free(data); //@ open proof_obligations(pub); //@ assert is_public_data(?proof, pub); //@ proof(i); //@ close proof_obligations(pub); network_send(net_stat, item); item_free(item); } }
void check_valid_symmetric_encrypted_item_size(int size) //@ requires true; //@ ensures size > TAG_LENGTH + GCM_IV_SIZE; { if (size <= TAG_LENGTH + GCM_KEY_SIZE) abort_crypto_lib("Illegal size for symmetric encrypted item"); }
int create_principal(struct keypair** keypair) /*@ requires world(?pub, ?key_clsfy) &*& pointer(keypair, _) &*& principals_created(?count); @*/ /*@ ensures world(pub, key_clsfy) &*& principals_created(result) &*& result == count + 1 &*& principal(result, 1) &*& pointer(keypair, ?p_keypair) &*& keypair(p_keypair, result, 1, 0, pub); @*/ { //@ open principals_created(count); //@ principal_create(); if (counter >= INT_MAX - 1) { abort_crypto_lib("To many principals generated"); } counter++; //@ close keypair_request(count + 1, 0); struct keypair *k = create_keypair(counter); *keypair = k; struct item *key = keypair_get_public_key(k); register_public_key(counter, key); item_free(key); return counter; //@ close principals_created(count + 1); }
struct item *get_public_key(int participant) //@ requires [?f]world(?pub, ?key_clsfy); /*@ ensures [f]world(pub, key_clsfy) &*& item(result, public_key_item(participant, 1), pub); @*/ { //@ open [f]world(pub, key_clsfy); //@ open [f]key_registry_initialized(pub); if (participant < 1) abort_crypto_lib("Participant does not exist"); struct item *result = 0; struct key_registry* current = registered_keys; while(current != 0 && result == 0) /*@ requires [f]key_registry(current, pub) &*& result == 0 ? true : item(result, public_key_item(participant, 1), pub); @*/ /*@ ensures [f]key_registry(old_current, pub) &*& result == 0 ? true : item(result, public_key_item(participant, 1), pub); @*/ { //@ open [f]key_registry(current, pub); if (current->participant == participant) { result = item_clone(current->pub_key); //@ close [f]key_registry(old_current, pub); break; } current = current->next; //@ recursive_call(); //@ close [f]key_registry(old_current, pub); } if (result == 0) abort_crypto_lib("Participant does not exist"); return result; //@ close [f]key_registry_initialized(pub); //@ close [f]world(pub, key_clsfy); }
void check_is_asymmetric_encrypted(struct item *item) //@ requires [?f]world(?pub, ?key_clsfy) &*& item(item, ?i, pub); /*@ ensures [f]world(pub, key_clsfy) &*& item(item, i, pub) &*& i == asymmetric_encrypted_item(_, _, _, _); @*/ { if (!is_asymmetric_encrypted(item)) abort_crypto_lib("Presented item is not an asymmetric encrypted item"); }
void check_is_pair(struct item *item) //@ requires [?f]world(?pub, ?key_clsfy) &*& item(item, ?p, pub); /*@ ensures [f]world(pub, key_clsfy) &*& item(item, p, pub) &*& p == pair_item(_, _); @*/ { if (!is_pair(item)) abort_crypto_lib("Presented item is not a pair item"); }
void *malloc_wrapper(int size) //@ requires 0 <= size; /*@ ensures result != 0 &*& malloc_block(result, size) &*& chars(result, size, ?cs) &*& true == ((char *)0 < result && result + size <= (char *)UINTPTR_MAX); @*/ { if (size > MAX_PACKAGE_SIZE) abort_crypto_lib("Requested humongous malloc!!!!!!!!"); void* result = malloc(size); if (result == 0) abort_crypto_lib("Malloc failed"); return result; }
struct item* item_clone(struct item* item) //@ requires [?f]item(item, ?i, ?pub); /*@ ensures [f]item(item, i, pub) &*& item(result, i, pub) &*& result != 0; @*/ { //@ open [f]item(item, i, pub); struct item* clone = malloc(sizeof(struct item)); if (clone == 0){abort_crypto_lib("malloc of item failed");} clone->size = item->size; clone->content = malloc_wrapper(clone->size); memcpy(clone->content, item->content, (unsigned int) clone->size); return clone; //@ close [f]item(item, i, pub); //@ close item(clone, i, pub); }
void register_public_key(int participant, struct item *key) /*@ requires world(?pub, ?key_clsfy) &*& item(key, public_key_item(participant, 1), pub); @*/ /*@ ensures world(pub, key_clsfy) &*& item(key, public_key_item(participant, 1), pub); @*/ { struct item* clone = item_clone(key); //@ open world(pub, key_clsfy); struct key_registry *kr = malloc(sizeof(struct key_registry)); if (kr == 0) {abort_crypto_lib("malloc failed");} //@ open key_registry_initialized(pub); kr->participant = participant; kr->pub_key = clone; kr->next = registered_keys; registered_keys = kr; //@ assert pointer(®istered_keys, ?head); //@ close key_registry(head, pub); //@ close key_registry_initialized(pub); //@ close world(pub, key_clsfy); }
void pair_get_components(struct item* pair, struct item** firstp, struct item** secondp) /*@ requires [?f]world(?pub, ?key_clsfy) &*& item(pair, ?p, pub) &*& p == pair_item(?f0, ?s0) &*& pointer(firstp, _) &*& pointer(secondp, _); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& item(pair, p, pub) &*& pointer(firstp, ?fp) &*& pointer(secondp, ?sp) &*& item(fp, ?f1, pub) &*& item(sp, ?s1, pub) &*& col ? true : f0 == f1 && s0 == s1; @*/ { char* temp; check_is_pair(pair); //@ open item(pair, p, pub); //@ assert pair->content |-> ?cont &*& pair->size |-> ?size; //@ assert crypto_chars(secret, cont, size, ?cs); //@ open [_]item_constraints(p, cs, pub); //@ assert [_]ic_parts(p)(?cs_tag, ?cs_cont); //@ take_append(TAG_LENGTH, cs_tag, cs_cont); //@ drop_append(TAG_LENGTH, cs_tag, cs_cont); //@ assert [_]ic_pair(p)(?cs_f, ?cs_s); struct item *first = malloc(sizeof(struct item)); struct item *second = malloc(sizeof(struct item)); if (first == 0 || second == 0){abort_crypto_lib("malloc of item failed");} temp = pair->content; //@ crypto_chars_split(cont, TAG_LENGTH); //@ if (col) public_generated_split(polarssl_pub(pub), cs, TAG_LENGTH); //@ assert crypto_chars(secret, temp, TAG_LENGTH, cs_tag); //@ assert crypto_chars(secret, temp + TAG_LENGTH, size - TAG_LENGTH, cs_cont); //@ assert cs_tag == full_tag(TAG_PAIR); //@ assert cs == append(cs_tag, cs_cont); //@ switch(cs_tag) {case cons(c0, cs0): case nil: assert false;} //@ assert cs_tag == cons(TAG_PAIR, _); temp = temp + TAG_LENGTH; if (pair->size <= TAG_LENGTH + (int) sizeof(int)) abort_crypto_lib("Found corrupted pair item 1"); //@ open [f]world(pub, key_clsfy); //@ crypto_chars_split(temp, sizeof(int)); //@ if (col) public_generated_split(polarssl_pub(pub), cs_cont, sizeof(int)); //@ assert crypto_chars(secret, temp, sizeof(int), ?cs_size_f); //@ assert crypto_chars(secret, temp + sizeof(int), size - TAG_LENGTH - sizeof(int), ?cs_p); //@ take_append(sizeof(int), cs_size_f, cs_p); //@ drop_append(sizeof(int), cs_size_f, cs_p); //@ public_crypto_chars(temp, sizeof(int)); //@ chars_to_integer(temp); first->size = *((int*) (void*) temp); second->size = pair->size - TAG_LENGTH - (int) sizeof(int) - first->size; //@ assert first->size |-> ?size_f &*& second->size |-> ?size_s; if (first->size <= TAG_LENGTH || pair->size - TAG_LENGTH - (int) sizeof(int) <= first->size) abort_crypto_lib("Found corrupted pair item 2"); //@ integer_to_chars(temp); temp = temp + (int) sizeof(int); //@ assert cs_cont == append(cs_size_f, cs_p); //@ append_assoc(cs_cont, cs_size_f, cs_p); //@ crypto_chars_split(temp, first->size); //@ if (col) public_generated_split(polarssl_pub(pub), cs_p, first->size); //@ take_append(size_f, cs_f, cs_s); //@ drop_append(size_f, cs_f, cs_s); //@ assert crypto_chars(secret, temp, size_f, cs_f); //@ assert crypto_chars(secret, temp + size_f, size_s, cs_s); //@ assert cs_p == append(cs_f, cs_s); first->content = malloc_wrapper(first->size); if (first->size <= MINIMAL_STRING_SIZE) abort_crypto_lib("Found corrupted pair item 3"); memcpy(first->content, temp, (unsigned int) first->size); temp = temp + first->size; if (second->size <= MINIMAL_STRING_SIZE) abort_crypto_lib("Found corrupted pair item 4"); second->content = malloc_wrapper(second->size); memcpy(second->content, temp, (unsigned int) second->size); //@ crypto_chars_join(cont + TAG_LENGTH + sizeof(int)); //@ chars_to_secret_crypto_chars(cont + TAG_LENGTH, sizeof(int)); //@ crypto_chars_join(cont + TAG_LENGTH); //@ assert first->content |-> ?cont_f &*& second->content |-> ?cont_s; //@ assert crypto_chars(secret, cont_f, size_f, cs_f); //@ assert crypto_chars(secret, cont_s, size_s, cs_s); //@ assert size_f == int_of_chars(cs_size_f); //@ assert chars_of_unbounded_int(size_f) == cs_size_f; //@ assert length(cs_f) == size_f; //@ assert [_]item_constraints(f0, ?cs_f0, pub); //@ assert [_]item_constraints(s0, ?cs_s0, pub); /*@ drop_append(sizeof(int), chars_of_int(length(cs_f0)), append(cs_f0, cs_s0)); @*/ /*@ take_append(sizeof(int), chars_of_int(length(cs_f0)), append(cs_f0, cs_s0)); @*/ //@ drop_append(length(cs_f0), cs_f0, cs_s0); //@ take_append(length(cs_f0), cs_f0, cs_s0); //@ close item(first, f0, pub); //@ close item(second, s0, pub); //@ close item(pair, pair_item(f0, s0), pub); *firstp = first; *secondp = second; //@ close [f]world(pub, key_clsfy); }
struct item *asymmetric_encryption(struct item *key, struct item *payload) /*@ requires [?f]world(?pub, ?key_clsfy) &*& principal(?principal1, ?count1) &*& item(payload, ?pay, pub) &*& item(key, ?k, pub) &*& k == public_key_item(?principal2, ?count2); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& principal(principal1, count1 + 1) &*& item(payload, pay, pub) &*& item(key, k, pub) &*& item(result, ?enc, pub) &*& col ? true : enc == asymmetric_encrypted_item(principal2, count2, some(pay), ?ent); @*/ { debug_print("ASYM ENCRYPTING:\n"); print_item(payload); struct item* result; result = malloc(sizeof(struct item)); if (result == 0) abort_crypto_lib("Malloc failed"); { pk_context context; unsigned int olen; char output[MAX_PACKAGE_SIZE]; // Key //@ close pk_context(&context); //@ open [f]world(pub, key_clsfy); pk_init(&context); //@ close [f]world(pub, key_clsfy); set_public_key(&context, key); //@ open [f]world(pub, key_clsfy); /*@ assert pk_context_with_key(&context, pk_public, ?principal, ?count, RSA_BIT_KEY_SIZE); @*/ //@ assert col || principal == principal2; //@ assert col || count == count2; // Encryption //@ open item(payload, pay, pub); //@ assert [_]item_constraints(pay, ?pay_cs, pub); if (payload->size > RSA_KEY_SIZE) abort_crypto_lib("Asymmetric encryption failed: incorrect sizes"); void *random_state = nonces_expose_state(); //@ close random_state_predicate(havege_state_initialized); /*@ produce_function_pointer_chunk random_function( asym_enc_havege_random_stub) (havege_state_initialized)(state, out, len) { call(); } @*/ //@ open principal(principal1, count1); if(pk_encrypt(&context, payload->content, (unsigned int) payload->size, output, &olen, MAX_PACKAGE_SIZE, asym_enc_havege_random_stub, random_state) != 0) abort_crypto_lib("Encryption failed"); //@ close principal(principal1, count1 + 1); //@ open cryptogram(output, ?enc_length, ?enc_cs, ?enc_cg); //@ assert enc_cg == cg_asym_encrypted(principal, count, pay_cs, ?ent); //@ assert u_integer(&olen, enc_length); //@ assert enc_length > 0 &*& enc_length < MAX_PACKAGE_SIZE; //@ assert enc_length > 0 &*& enc_length <= RSA_SERIALIZED_KEY_SIZE; nonces_hide_state(random_state); //@ pk_release_context_with_key(&context); pk_free(&context); //@ open pk_context(&context); //@ close [f]world(pub, key_clsfy); // Create item result->size = TAG_LENGTH + (int) olen; result->content = malloc(result->size); if (result->content == 0) {abort_crypto_lib("Malloc failed");} write_tag(result->content, TAG_ASYMMETRIC_ENC); //@ assert result->content |-> ?cont &*& result->size |-> ?size; if (olen < MINIMAL_STRING_SIZE) {abort_crypto_lib("Asymmetric encryption failed: to small");} memcpy(result->content + TAG_LENGTH, output, olen); //@ assert chars(cont, TAG_LENGTH, ?cs_tag); //@ public_chars(cont, TAG_LENGTH); //@ chars_to_secret_crypto_chars(cont, TAG_LENGTH); //@ assert cs_tag == full_tag(TAG_ASYMMETRIC_ENC); //@ crypto_chars_join(cont); //@ item enc = asymmetric_encrypted_item(principal, count, some(pay), ent); //@ list<char> cs = append(cs_tag, enc_cs); //@ WELL_FORMED(cs_tag, enc_cs, TAG_ASYMMETRIC_ENC) //@ close ic_parts(enc)(cs_tag, enc_cs); //@ close ic_cg(enc)(enc_cs, enc_cg); /*@ if (col) { crypto_chars_to_chars(cont, size); public_chars(cont, size); chars_to_secret_crypto_chars(cont, size); public_generated_split(polarssl_pub(pub), cs, TAG_LENGTH); } @*/ //@ well_formed_item_constraints(pay, enc); //@ close item_constraints(enc, cs, pub); //@ leak item_constraints(enc, cs, pub); //@ close item(result, enc, pub); zeroize(output, (int) olen); //@ chars_join(output); //@ close item(payload, pay, pub); } debug_print("ENCRYPTING RESULT:\n"); print_item(result); return result; }
struct item *asymmetric_decryption(struct item *key, struct item *item, char tag) /*@ requires [?f]world(?pub, ?key_clsfy) &*& true == valid_tag(tag) &*& principal(?principal1, ?count1) &*& item(item, ?enc, pub) &*& item(key, ?k, pub) &*& enc == asymmetric_encrypted_item(?principal2, ?count2, ?pay, ?ent) &*& k == private_key_item(?principal3, ?count3); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& principal(principal1, count1 + 1) &*& item(item, enc, pub) &*& item(key, k, pub) &*& item(result, ?dec, pub) &*& tag_for_item(dec) == tag &*& col ? [_]pub(dec) : principal2 != principal3 || count2 != count3 ? true == key_clsfy(principal3, count3, false) &*& [_]pub(dec) : switch(pay) { case some(dec2): return dec == dec2; case none: return false; }; @*/ { struct item* result = 0; debug_print("DECRYPTING:\n"); print_item(item); check_is_asymmetric_encrypted(item); { pk_context context; unsigned int olen; char output[MAX_PACKAGE_SIZE]; // Key //@ close pk_context(&context); //@ open [f]world(pub, key_clsfy); pk_init(&context); //@ close [f]world(pub, key_clsfy); set_private_key(&context, key); //@ open [f]world(pub, key_clsfy); /*@ assert pk_context_with_key(&context, pk_private, ?principal, ?count, RSA_BIT_KEY_SIZE); @*/ // Decryption //@ open item(item, enc, pub); /*@ assert enc == asymmetric_encrypted_item(principal2, count2, pay, ent); @*/ //@ open [_]item_constraints(enc, ?enc_cs, pub); //@ assert [_]ic_parts(enc)(?enc_tag, ?enc_cont); //@ assert enc_cs == append(enc_tag, enc_cont); //@ open [_]ic_cg(enc)(_, ?enc_cg); //@ assert enc_cg == cg_asym_encrypted(principal2, count2, ?cs_pay, ent); if (item->size - TAG_LENGTH > RSA_KEY_SIZE || item->size - TAG_LENGTH < MINIMAL_STRING_SIZE) abort_crypto_lib("Asymmetric decryption failed: incorrect sizes"); //@ assert item->content |-> ?i_cont &*& item->size |-> ?i_size; //@ crypto_chars_split(i_cont, TAG_LENGTH); //@ drop_append(TAG_LENGTH, enc_tag, enc_cont); //@ assert crypto_chars(secret, i_cont + TAG_LENGTH, i_size - TAG_LENGTH, enc_cont); //@ if (col) enc_cg = chars_for_cg_sur(enc_cont, tag_asym_encrypted); //@ if (col) public_crypto_chars_extract(i_cont + TAG_LENGTH, enc_cg); //@ close cryptogram(i_cont + TAG_LENGTH, i_size - TAG_LENGTH, enc_cont, enc_cg); void *random_state = nonces_expose_state(); //@ close random_state_predicate(havege_state_initialized); /*@ produce_function_pointer_chunk random_function( asym_enc_havege_random_stub) (havege_state_initialized)(state, out, len) { call(); } @*/ //@ open principal(principal1, count1); //@ structure s = known_value(0, full_tag(tag)); //@ close decryption_pre(false, false, principal1, s, enc_cont); if(pk_decrypt(&context, item->content + TAG_LENGTH, (unsigned int) item->size - TAG_LENGTH, output, &olen, MAX_PACKAGE_SIZE, asym_enc_havege_random_stub, random_state) != 0) abort_crypto_lib("Decryption failed"); /*@ open decryption_post(false, ?garbage, principal1, s, ?p_key, ?c_key, ?cs_out); @*/ //@ assert u_integer(&olen, ?size_out); //@ pk_release_context_with_key(&context); //@ open cryptogram(i_cont + TAG_LENGTH, i_size - TAG_LENGTH, enc_cont, enc_cg); pk_free(&context); //@ open pk_context(&context); nonces_hide_state(random_state); //@ assert chars((void*)output + size_out, MAX_PACKAGE_SIZE - size_out, ?cs_rest); result = malloc(sizeof(struct item)); if (result == 0) {abort_crypto_lib("Malloc failed");} result->size = (int) olen; if ((int) olen <= MINIMAL_STRING_SIZE) abort_crypto_lib("Decryption: Incorrect size"); result->content = malloc(result->size); if (result->content == 0) {abort_crypto_lib("Malloc failed");} //@ close [f]world(pub, key_clsfy); //@ assert u_integer(&olen, ?olen_val); //@ assert crypto_chars(_, output, olen_val, cs_out); //@ crypto_chars_split(output, TAG_LENGTH); //@ assert crypto_chars(_, output, TAG_LENGTH, ?cs_tag); //@ assert crypto_chars(_, (void*) output + TAG_LENGTH, olen_val - TAG_LENGTH, ?cs_i); /*@ if (col) { crypto_chars_to_chars(output, TAG_LENGTH); chars_to_crypto_chars(output, TAG_LENGTH); } else if (!garbage) { switch(pay) { case some(pay1): open [_]item_constraints(pay1, cs_out, pub); case none: open [_]ill_formed_item_chars(enc)(cs_out); public_generated_split(polarssl_pub(pub), cs_out, TAG_LENGTH); } public_crypto_chars(output, TAG_LENGTH); } @*/ //@ close check_tag2_ghost_args(false, garbage, p_key, c_key, cs_i); check_tag2(output, tag); //@ if (!garbage) chars_to_secret_crypto_chars(output, TAG_LENGTH); //@ crypto_chars_join(output); memcpy(result->content, output, olen); //@ assert result->content |-> ?cont; //@ assert crypto_chars(?kind, cont, olen_val, cs_out); zeroize(output, (int) olen); //@ close item(item, enc, pub); //@ assert enc == asymmetric_encrypted_item(principal2, count2, pay, ent); //@ assert col || enc_cg == cg_asym_encrypted(principal2, count2, cs_pay, ent); /*@ if (col) { crypto_chars_to_chars(cont, olen_val); public_chars(cont, olen_val); chars_to_crypto_chars(cont, olen_val); } else if (garbage) { assert true == key_clsfy(principal3, count3, false); public_chars(cont, olen_val); chars_to_crypto_chars(cont, olen_val); } else { assert principal2 == principal3; assert count2 == count3; assert cs_out == cs_pay; switch(pay) { case some(pay1): assert [_]item_constraints(pay1, cs_out, pub); case none: open [_]ill_formed_item_chars(enc)(cs_out); assert [_]public_generated(polarssl_pub(pub))(cs_out); public_crypto_chars(cont, olen_val); chars_to_crypto_chars(cont, olen_val); } } @*/ parse_item(result->content, (int) olen); /*@ if (col || garbage) { retreive_proof_obligations(); deserialize_item(cs_out, pub); leak proof_obligations(pub); chars_to_secret_crypto_chars(cont, olen_val); } @*/ //@ open [_]item_constraints(?dec, cs_out, pub); //@ assert [_]ic_parts(dec)(?dec_tag, ?dec_cont); //@ take_append(TAG_LENGTH, dec_tag, dec_cont); //@ drop_append(TAG_LENGTH, dec_tag, dec_cont); //@ assert dec_tag == full_tag(tag); //@ assert tag_for_item(dec) == tag; //@ close item(result, dec, pub); } return result; }
void parse_pair_item(char* message, int size) /*@ requires FORALLP_C &*& FORALLP_CS &*& [?f1]world(?pub, ?key_clsfy) &*& exists(?ccs_tag) &*& ccs_tag == full_ctag(c_to_cc(TAG_PAIR)) &*& TAG_LENGTH == length(ccs_tag) &*& size <= INT_MAX - TAG_LENGTH &*& head(ccs_tag) == c_to_cc(TAG_PAIR) &*& [?f2]crypto_chars(?kind, message, size, ?ccs_cont) &*& switch(kind) { case normal: return true; case secret: return [_]item_constraints(pair_item(_, _), append(ccs_tag, ccs_cont), pub); }; @*/ /*@ ensures [f1]world(pub, key_clsfy) &*& [f2]crypto_chars(kind, message, size, ccs_cont) &*& true == well_formed_ccs(forallc, forallcs, nat_length(append(ccs_tag, ccs_cont)), append(ccs_tag, ccs_cont)); @*/ { //@ open [f1]world(pub, key_clsfy); //@ close [f1]world(pub, key_clsfy); if (size <= (int) sizeof(int)) abort_crypto_lib("Incorrect size for pair item"); //@ list<crypto_char> ccs = append(ccs_tag, ccs_cont); //@ take_append(TAG_LENGTH, ccs_tag, ccs_cont); //@ drop_append(TAG_LENGTH, ccs_tag, ccs_cont); //@ crypto_chars_limits(message); //@ crypto_chars_split(message, sizeof(int)); //@ assert [f2]crypto_chars(kind, message, sizeof(int), ?size_f_ccs); /*@ assert [f2]crypto_chars(kind, message + sizeof(int), size - sizeof(int), ?ccs_p); @*/ //@ take_append(sizeof(int), size_f_ccs, ccs_p); //@ drop_append(sizeof(int), size_f_ccs, ccs_p); //@ assert ccs_cont == append(size_f_ccs, ccs_p); /*@ if (kind == secret) { assert [_]item_constraints(?p, ccs, pub); OPEN_ITEM_CONSTRAINTS(p, ccs, pub); public_crypto_chars(message, sizeof(int)); } else { crypto_chars_to_chars(message, sizeof(int)); } @*/ //@ assert [f2]chars(message, sizeof(int), ?size_f_cs); //@ assert cs_to_ccs(size_f_cs) == size_f_ccs; //@ chars_to_integer(message); int size_f = *((int*) ((void*) message)); //@ assert size_f == int_of_chars(size_f_cs); //@ integer_to_chars(message); if (size_f < MINIMAL_STRING_SIZE || size_f > size - (int) sizeof(int)) abort_crypto_lib("Incorrect size for pair item"); int size_s = size - (int) sizeof(int) - size_f; //@ crypto_chars_limits(message + sizeof(int)); //@ crypto_chars_split(message + sizeof(int), size_f); /*@ assert [f2]crypto_chars(kind, message + (int) sizeof(int), size_f, ?ccs_f); @*/ /*@ assert [f2]crypto_chars(kind, message + (int) sizeof(int) + size_f, size_s, ?ccs_s); @*/ //@ take_append(size_f, ccs_f, ccs_s); //@ drop_append(size_f, ccs_f, ccs_s); //@ assert ccs_p == append(ccs_f, ccs_s); if (size_f <= TAG_LENGTH || size_s <= TAG_LENGTH) abort_crypto_lib("Incorrect size for pair item"); /*@ assert ccs_cont == append(cs_to_ccs(chars_of_unbounded_int(length(ccs_f))), append(ccs_f, ccs_s)); @*/ /*@ if (kind == secret) { assert [_]item_constraints(?p, ccs, pub); OPEN_ITEM_CONSTRAINTS(p, ccs, pub); assert [_]ic_pair(p)(?ccs_f0, ?ccs_s0); assert [_]item_constraints(_, ccs_f0, pub); assert [_]item_constraints(_, ccs_s0, pub); cs_to_ccs_inj(chars_of_int(length(ccs_f)), chars_of_int(length(ccs_f0))); take_append(size_f, ccs_f0, ccs_s0); drop_append(size_f, ccs_f0, ccs_s0); } @*/ parse_item(message + (int) sizeof(int), size_f); parse_item(message + (int) sizeof(int) + size_f, size_s); //@ crypto_chars_join(message + sizeof(int)); //@ if (kind == normal) chars_to_crypto_chars(message, sizeof(int)); //@ if (kind == secret) chars_to_secret_crypto_chars(message, sizeof(int)); //@ crypto_chars_join(message); //@ length_equals_nat_length(ccs); //@ length_equals_nat_length(ccs_cont); /*@ switch(nat_length(ccs)) { case succ(n): well_formed_upper_bound(nat_length(ccs_f), nat_length(ccs_cont), ccs_f); well_formed_upper_bound(nat_length(ccs_s), nat_length(ccs_cont), ccs_s); assert length(ccs) > 0; assert length(ccs) <= INT_MAX; assert true == well_formed_ccs(forallc, forallcs, nat_length(ccs_f), ccs_f); assert true == well_formed_ccs(forallc, forallcs, nat_length(ccs_s), ccs_s); head_append(ccs_tag, ccs_cont); well_formed_pair_item(ccs, size_f, ccs_f, ccs_s); case zero: assert false; } @*/ }
struct item *symmetric_encryption(struct item *key, struct item *payload) /*@ requires [?f]world(?pub, ?key_clsfy) &*& principal(?principal1, ?count1) &*& [_]pub(nonce_item(principal1, count1 + 1, 0)) &*& item(payload, ?pay, pub) &*& item(key, ?k, pub) &*& k == symmetric_key_item(?principal2, ?count2); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& principal(principal1, count1 + 2) &*& item(payload, pay, pub) &*& item(key, k, pub) &*& item(result, ?enc, pub) &*& col ? true : enc == symmetric_encrypted_item(principal2, count2, some(pay), ?ent); @*/ { //@ open [f]world(pub, key_clsfy); debug_print("ENCRYPTING:\n"); print_item(payload); struct item* result; result = malloc(sizeof(struct item)); if (result == 0) abort_crypto_lib("Malloc failed"); { gcm_context gcm_context; char iv_buffer[GCM_IV_SIZE]; char *iv; char *result_cs; char *encrypted; //@ open item(key, k, pub); //@ assert key->content |-> ?k_cont &*& key->size |-> ?k_size; check_valid_symmetric_key_item_size(key->size); //@ open [_]item_constraints(k, ?k_cs0, pub); //@ assert [_]ic_parts(k)(?k_tag, ?k_cs); //@ crypto_chars_limits(k_cont); //@ crypto_chars_split(k_cont, TAG_LENGTH); //@ WELL_FORMED(k_tag, k_cs, TAG_SYMMETRIC_KEY) //@ assert crypto_chars(secret, k_cont, TAG_LENGTH, k_tag); //@ assert crypto_chars(secret, k_cont + TAG_LENGTH, GCM_KEY_SIZE, k_cs); //@ cryptogram k_cg = cg_symmetric_key(principal2, count2); //@ if (col) k_cg = chars_for_cg_sur(k_cs, tag_symmetric_key); //@ if (col) crypto_chars_to_chars(k_cont + TAG_LENGTH, GCM_KEY_SIZE); //@ if (col) public_chars_extract(k_cont + TAG_LENGTH, k_cg); //@ if (col) chars_to_secret_crypto_chars(k_cont + TAG_LENGTH, GCM_KEY_SIZE); //@ close cryptogram(k_cont + TAG_LENGTH, GCM_KEY_SIZE, k_cs, k_cg); //@ close gcm_context(&gcm_context); if (gcm_init(&gcm_context, POLARSSL_CIPHER_ID_AES, (key->content + TAG_LENGTH), (unsigned int) GCM_KEY_SIZE * 8) != 0) abort_crypto_lib("Init gcm failed"); //@ assert gcm_context_initialized(&gcm_context, ?p, ?c); //@ assert col || (p == principal2 && c == count2); //@ open cryptogram(k_cont + TAG_LENGTH, GCM_KEY_SIZE, k_cs, k_cg); //@ crypto_chars_join(k_cont); //@ close item(key, k, pub); //@ open item(payload, pay, pub); //@ open [_]item_constraints(pay, ?pay_cs, pub); //@ assert payload->content |-> ?p_cont &*& payload->size |-> ?p_size; //@ crypto_chars_limits(p_cont); if (payload->size >= INT_MAX - TAG_LENGTH - GCM_IV_SIZE - GCM_MAC_SIZE || payload->size < MINIMAL_STRING_SIZE) abort_crypto_lib("Gcm encryption failed: incorrect sizes"); result->size = TAG_LENGTH + GCM_IV_SIZE + GCM_MAC_SIZE + payload->size; result->content = malloc(result->size); //@ assert result->content |-> ?r_cont &*& result->size |-> ?r_size; if (result->content == 0) abort_crypto_lib("Malloc failed"); //@ chars_split(r_cont, TAG_LENGTH); write_tag(result->content, TAG_SYMMETRIC_ENC); //@ assert chars(r_cont, TAG_LENGTH, ?tag_cs); //@ public_chars(r_cont, TAG_LENGTH); //@ assert tag_cs == full_tag(TAG_SYMMETRIC_ENC); //@ assert chars(r_cont + TAG_LENGTH, GCM_IV_SIZE + p_size, _); //@ chars_split(r_cont + TAG_LENGTH, GCM_IV_SIZE); iv = result->content + TAG_LENGTH; //@ close nonce_request(principal1, 0); //@ close [f]world(pub, key_clsfy); create_havege_random(iv, GCM_IV_SIZE); //@ open cryptogram(iv, GCM_IV_SIZE, ?iv_cs, ?iv_cg); memcpy(iv_buffer, iv, GCM_IV_SIZE); //@ close cryptogram(iv, GCM_IV_SIZE, iv_cs, iv_cg); //@ close polarssl_pub(pub)(iv_cg); //@ leak polarssl_pub(pub)(iv_cg); //@ public_cryptogram(iv, iv_cg); //@ public_chars(iv, GCM_IV_SIZE); encrypted = iv + GCM_IV_SIZE; //@ chars_split(encrypted, GCM_MAC_SIZE); //@ open principal(principal1, count1 + 1); if (gcm_crypt_and_tag(&gcm_context, GCM_ENCRYPT, (unsigned int) payload->size, iv_buffer, GCM_IV_SIZE, NULL, 0, payload->content, encrypted + GCM_MAC_SIZE, GCM_MAC_SIZE, encrypted) != 0) abort_crypto_lib("Gcm encryption failed"); //@ close principal(principal1, count1 + 2); zeroize(iv_buffer, GCM_IV_SIZE); //@ assert crypto_chars(secret, encrypted, GCM_MAC_SIZE, ?mac_cs); //@ assert crypto_chars(secret, encrypted + GCM_MAC_SIZE, p_size, ?enc_cs); //@ crypto_chars_join(encrypted); //@ assert exists(?enc_cg); //@ list<char> cg_cs = append(mac_cs, enc_cs); //@ assert cg_cs == chars_for_cg(enc_cg); //@ list<char> cont_cs = append(iv_cs, cg_cs); //@ take_append(GCM_IV_SIZE, iv_cs, cg_cs); //@ drop_append(GCM_IV_SIZE, iv_cs, cg_cs); //@ list<char> cs = append(tag_cs, cont_cs); //@ take_append(TAG_LENGTH, tag_cs, cont_cs); //@ drop_append(TAG_LENGTH, tag_cs, cont_cs); //@ item enc; //@ list<char> ent = append(iv_cs, iv_cs); //@ take_append(GCM_IV_SIZE, iv_cs, iv_cs); //@ drop_append(GCM_IV_SIZE, iv_cs, iv_cs); /*@ if (col) { enc_cg = chars_for_cg_sur(cg_cs, tag_auth_encrypted); assert enc_cg == cg_auth_encrypted(?p0, ?c0, ?pay0, ?iv0); ent = append(iv_cs, iv0); take_append(GCM_IV_SIZE, iv_cs, iv0); drop_append(GCM_IV_SIZE, iv_cs, iv0); enc = symmetric_encrypted_item(p0, c0, some(pay), ent); public_chars(encrypted, GCM_MAC_SIZE + p_size); assert chars(encrypted, GCM_MAC_SIZE + p_size, cg_cs); chars_join(iv); chars_join(r_cont); assert chars(r_cont, r_size, cs); public_chars(r_cont, r_size); public_generated_split(polarssl_pub(pub), cs, TAG_LENGTH); close ic_sym_enc(enc)(iv0, cg_cs); } else { assert enc_cg == cg_auth_encrypted(principal2, count2, pay_cs, iv_cs); enc = symmetric_encrypted_item(principal2, count2, some(pay), ent); close polarssl_pub(pub)(cg_nonce(principal1, count1 + 1)); leak polarssl_pub(pub)(cg_nonce(principal1, count1 + 1)); public_generated(polarssl_pub(pub), cg_nonce(principal1, count1 + 1)); chars_to_secret_crypto_chars(iv, GCM_IV_SIZE); crypto_chars_join(iv); chars_to_secret_crypto_chars(r_cont, TAG_LENGTH); crypto_chars_join(r_cont); assert crypto_chars(secret, r_cont, r_size, cs); close ic_sym_enc(enc)(iv_cs, cg_cs); } @*/ //@ well_formed_item_constraints(pay, enc); //@ close ic_cg(enc)(cg_cs, enc_cg); //@ close ic_parts(enc)(tag_cs, cont_cs); //@ WELL_FORMED(tag_cs, cont_cs, TAG_SYMMETRIC_ENC) //@ close item_constraints(enc, cs, pub); //@ leak item_constraints(enc, cs, pub); //@ close item(result, enc, pub); //@ close item(payload, pay, pub); gcm_free(&gcm_context); //@ open gcm_context(&gcm_context); } debug_print("ENCRYPTING RESULT:\n"); print_item(result); return result; }
struct item *symmetric_decryption(struct item *key, struct item *item) /*@ requires [?f]world(?pub, ?key_clsfy) &*& item(item, ?enc, pub) &*& enc == symmetric_encrypted_item(?principal1, ?count1, ?pay, ?ent) &*& item(key, ?k, pub) &*& k == symmetric_key_item(?principal2, ?count2); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& item(item, enc, pub) &*& item(key, k, pub) &*& item(result, ?dec, pub) &*& col ? [_]pub(dec) : switch(pay) { case some(dec2): return principal1 == principal2 && count1 == count2 && dec == dec2; case none: return false; }; @*/ { debug_print("DECRYPTING:\n"); print_item(item); check_is_symmetric_encrypted(item); //@ open [f]world(pub, key_clsfy); struct item* result; result = malloc(sizeof(struct item)); if (result == 0) abort_crypto_lib("Malloc failed"); { gcm_context gcm_context; char *iv; char iv_buffer[GCM_IV_SIZE]; char *encrypted; //@ open item(key, k, pub); //@ assert key->content |-> ?k_cont &*& key->size |-> ?k_size; check_valid_symmetric_key_item_size(key->size); //@ open [_]item_constraints(k, ?k_cs0, pub); //@ assert [_]ic_parts(k)(?k_tag, ?k_cs); //@ crypto_chars_limits(k_cont); //@ crypto_chars_split(k_cont, TAG_LENGTH); //@ WELL_FORMED(k_tag, k_cs, TAG_SYMMETRIC_KEY) //@ assert crypto_chars(secret, k_cont, TAG_LENGTH, k_tag); //@ assert crypto_chars(secret, k_cont + TAG_LENGTH, GCM_KEY_SIZE, k_cs); //@ cryptogram k_cg = cg_symmetric_key(principal2, count2); //@ if (col) k_cg = chars_for_cg_sur(k_cs, tag_symmetric_key); //@ if (col) crypto_chars_to_chars(k_cont + TAG_LENGTH, GCM_KEY_SIZE); //@ if (col) public_chars_extract(k_cont + TAG_LENGTH, k_cg); //@ if (col) chars_to_secret_crypto_chars(k_cont + TAG_LENGTH, GCM_KEY_SIZE); //@ close cryptogram(k_cont + TAG_LENGTH, GCM_KEY_SIZE, k_cs, k_cg); //@ close gcm_context(&gcm_context); if (gcm_init(&gcm_context, POLARSSL_CIPHER_ID_AES, (key->content + TAG_LENGTH), (unsigned int) GCM_KEY_SIZE * 8) != 0) abort_crypto_lib("Init gcm failed"); //@ assert gcm_context_initialized(&gcm_context, ?p, ?c); //@ assert col || (p == principal2 && c == count2); //@ open cryptogram(k_cont + TAG_LENGTH, GCM_KEY_SIZE, k_cs, k_cg); //@ crypto_chars_join(k_cont); //@ close item(key, k, pub); //@ open item(item, enc, pub); //@ assert item->content |-> ?i_cont &*& item->size |-> ?i_size; //@ open [_]item_constraints(enc, ?cs, pub); //@ open [_]ic_parts(enc)(?enc_tag, ?enc_cont); //@ open [_]ic_cg(enc)(_, ?enc_cg); //@ take_append(TAG_LENGTH, enc_tag, enc_cont); //@ drop_append(TAG_LENGTH, enc_tag, enc_cont); //@ open [_]ic_sym_enc(enc)(?enc_iv, ?cg_cs); //@ assert true == well_formed(cs, nat_length(cs)); //@ close [1/2]hide_crypto_chars(_, i_cont, i_size, cs); check_valid_symmetric_encrypted_item_size(item->size); //@ assert length(cs) > TAG_LENGTH + GCM_IV_SIZE; int size = item->size - TAG_LENGTH - GCM_IV_SIZE - GCM_MAC_SIZE; if (size <= MINIMAL_STRING_SIZE) abort_crypto_lib("Gcm decryption failed"); //@ crypto_chars_limits(i_cont); //@ crypto_chars_split(i_cont, TAG_LENGTH); iv = item->content + TAG_LENGTH; //@ crypto_chars_split(iv, GCM_IV_SIZE); //@ assert [1/2]crypto_chars(secret, iv, GCM_IV_SIZE, ?iv_cs); memcpy(iv_buffer, iv, GCM_IV_SIZE); //@ assert cs == append(enc_tag, enc_cont); //@ assert enc_cont == append(iv_cs, cg_cs); //@ public_crypto_chars(iv, GCM_IV_SIZE); //@ chars_to_secret_crypto_chars(iv, GCM_IV_SIZE); encrypted = iv + GCM_IV_SIZE; //@ crypto_chars_limits(encrypted); //@ crypto_chars_split(encrypted, GCM_MAC_SIZE); //@ assert [1/2]crypto_chars(secret, encrypted, GCM_MAC_SIZE, ?mac_cs); /*@ assert [1/2]crypto_chars(secret, encrypted + GCM_MAC_SIZE, size, ?enc_cs); @*/ //@ assert cg_cs == append(mac_cs, enc_cs); result->size = size; result->content = malloc(size); if (result->content == 0) abort_crypto_lib("Malloc failed"); //@ assert result->content |-> ?r_cont &*& result->size |-> size; //@ if (col) enc_cg = chars_for_cg_sur(cg_cs, tag_auth_encrypted); //@ close exists(enc_cg); if (gcm_auth_decrypt(&gcm_context, (unsigned int) size, iv_buffer, GCM_IV_SIZE, NULL, 0, encrypted, GCM_MAC_SIZE, encrypted + GCM_MAC_SIZE, result->content) != 0) abort_crypto_lib("Gcm decryption failed"); //@ assert crypto_chars(secret, r_cont, size, ?dec_cs); //@ assert col || enc_cg == cg_auth_encrypted(principal1, count1, dec_cs, iv_cs); //@ crypto_chars_join(encrypted); //@ crypto_chars_join(iv); //@ crypto_chars_join(i_cont); //@ open [1/2]hide_crypto_chars(_, i_cont, i_size, cs); //@ close item(item, enc, pub); gcm_free(&gcm_context); //@ open gcm_context(&gcm_context); zeroize(iv_buffer, GCM_IV_SIZE); //@ close [f]world(pub, key_clsfy); /*@ if (col) { crypto_chars_to_chars(r_cont, size); chars_to_crypto_chars(r_cont, size); } else { assert enc == symmetric_encrypted_item(principal1, count1, pay, ent); assert enc_cg == cg_auth_encrypted(principal1, count1, dec_cs, enc_iv); switch(pay) { case some(pay1): assert [_]item_constraints(pay1, dec_cs, pub); case none: open [_]ill_formed_item_chars(enc)(dec_cs); assert [_]public_generated(polarssl_pub(pub))(dec_cs); public_crypto_chars(r_cont, size); chars_to_crypto_chars(r_cont, size); } } @*/ parse_item(result->content, size); /*@ if (col) { public_chars(r_cont, size); chars_to_secret_crypto_chars(r_cont, size); retreive_proof_obligations(); deserialize_item(dec_cs, pub); leak proof_obligations(pub); } @*/ //@ assert crypto_chars(secret, r_cont, size, dec_cs); //@ assert [_]item_constraints(?r, dec_cs, pub); //@ close item(result, r, pub); } debug_print("DECRYPTING RESULT:\n"); print_item(result); return result; }
void parse_item(char* buffer, int size) /*@ requires FORALLP_C &*& FORALLP_CS &*& [?f1]world(?pub, ?key_clsfy) &*& [?f2]crypto_chars(?kind, buffer, size, ?ccs) &*& size > TAG_LENGTH &*& kind == normal ? true : [_]item_constraints(?i, ccs, pub); @*/ /*@ ensures [f1]world(pub, key_clsfy) &*& [f2]crypto_chars(kind, buffer, size, ccs) &*& true == well_formed_ccs(forallc, forallcs, nat_length(ccs), ccs); @*/ { //@ open [f1]world(pub, key_clsfy); //@ close [f1]world(pub, key_clsfy); //@ crypto_chars_limits(buffer); //@ crypto_chars_split(buffer, TAG_LENGTH); //@ assert [f2]crypto_chars(kind, buffer, TAG_LENGTH, ?ccs_tag); /*@ assert [f2]crypto_chars(kind, buffer + TAG_LENGTH, size - TAG_LENGTH, ?cs_cont); @*/ /*@ switch (kind) { case normal: crypto_chars_to_chars(buffer, TAG_LENGTH); case secret: assert [_]item_constraints(?i, ccs, pub); OPEN_ITEM_CONSTRAINTS(i, ccs, pub); public_crypto_chars(buffer, TAG_LENGTH); } @*/ //@ open [f2]chars(buffer, TAG_LENGTH, ?cs_tag); //@ assert ccs_tag == cs_to_ccs(cs_tag); char t = *(buffer); //@ close [f2]chars(buffer, TAG_LENGTH, cs_tag); check_tag(buffer, t); //@ cs_to_ccs_full_tag(t); //@ assert cs_tag == full_tag(t); //@ length_equals_nat_length(ccs); //@ SWITCH_TAG(t) switch (t) { case TAG_DATA: break; case TAG_PAIR: //@ close exists(ccs_tag); parse_pair_item(buffer + TAG_LENGTH, size - TAG_LENGTH); break; case TAG_NONCE: if (size != TAG_LENGTH + 1 + NONCE_SIZE) abort_crypto_lib("Could not parse nonce: illegal size"); break; case TAG_HASH: if (size != TAG_LENGTH + HASH_SIZE) abort_crypto_lib("Could not parse hash: illegal size"); break; case TAG_SYMMETRIC_KEY: if (size != TAG_LENGTH + GCM_KEY_SIZE) abort_crypto_lib("Could not parse symmetric key: illegal size"); break; case TAG_PUBLIC_KEY: if (size != TAG_LENGTH + RSA_SERIALIZED_KEY_SIZE) abort_crypto_lib("Could not parse public key: illegal size"); break; case TAG_PRIVATE_KEY: if (size != TAG_LENGTH + RSA_SERIALIZED_KEY_SIZE) abort_crypto_lib("Could not parse private key: illegal size"); break; case TAG_HMAC: if (size != TAG_LENGTH + HMAC_SIZE) abort_crypto_lib("Could not parse private key: illegal size"); break; case TAG_SYMMETRIC_ENC: if (size < TAG_LENGTH + GCM_IV_SIZE + MINIMAL_STRING_SIZE) abort_crypto_lib("Could not parse symmetric encrypted item: illegal size"); break; case TAG_ASYMMETRIC_ENC: if (size > TAG_LENGTH + RSA_SERIALIZED_KEY_SIZE || size < TAG_LENGTH + MINIMAL_STRING_SIZE) abort_crypto_lib("Could not parse asymmetric encrypted item: illegal size"); break; case TAG_ASYMMETRIC_SIG: if (size > TAG_LENGTH + RSA_SERIALIZED_KEY_SIZE || size < TAG_LENGTH + MINIMAL_STRING_SIZE) abort_crypto_lib("Could not parse asymmetric signature item: illegal size"); break; default: abort_crypto_lib("Found illegal tag during deserialization"); } /*@ if (!exists_t<char>(forallc, (valid_ctag)(head(ccs)))) { forall_t_elim(forallc, (notf)((valid_ctag)(head(ccs))), t); assert false; } @*/ //@ assert true == well_formed_ccs(forallc, forallcs, nat_length(ccs), ccs); //@ if (kind == normal) chars_to_crypto_chars(buffer, TAG_LENGTH); //@ if (kind == secret) chars_to_secret_crypto_chars(buffer, TAG_LENGTH); //@ crypto_chars_join(buffer); }
struct item *asymmetric_signature(struct item *key, struct item *payload) /*@ requires [?f]world(?pub, ?key_clsfy) &*& principal(?principal1, ?count1) &*& item(payload, ?pay, pub) &*& item(key, ?k, pub) &*& k == private_key_item(?principal2, ?count2); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& principal(principal1, count1 + 1) &*& item(payload, pay, pub) &*& item(key, k, pub) &*& item(result, ?sig, pub) &*& col ? true : sig == asymmetric_signature_item(principal2, count2, some(pay), ?ent); @*/ { debug_print("ASYM SIGNING:\n"); print_item(payload); struct item* result; result = malloc(sizeof(struct item)); if (result == 0) abort_crypto_lib("Malloc failed"); debug_print("signing item\n"); print_item(payload); print_item(key); { pk_context context; unsigned int olen; char* output; // Key //@ close pk_context(&context); //@ open [f]world(pub, key_clsfy); pk_init(&context); //@ close [f]world(pub, key_clsfy); set_private_key(&context, key); //@ open [f]world(pub, key_clsfy); /*@ assert pk_context_with_key(&context, pk_private, ?principal, ?count, RSA_BIT_KEY_SIZE); @*/ //@ assert col || principal == principal2; //@ assert col || count == count2; // Payload //@ open item(payload, pay, pub); //@ open [_]item_constraints(pay, ?pay_cs, pub); //@ assert payload->content |-> ?p_cont &*& payload->size |-> ?p_size; if (payload->size > RSA_KEY_SIZE) abort_crypto_lib("Assymetric signing failed: incorrect size"); output = malloc(RSA_KEY_SIZE); if (output == 0) abort_crypto_lib("Malloc failed"); void *random_state = nonces_expose_state(); //@ close random_state_predicate(havege_state_initialized); /*@ produce_function_pointer_chunk random_function( asym_sig_havege_random_stub) (havege_state_initialized)(state, out, len) { call(); } @*/ //@ open principal(principal1, count1); if(pk_sign(&context, POLARSSL_MD_NONE, payload->content, (unsigned int) payload->size, output, &olen, asym_sig_havege_random_stub, random_state) != 0) abort_crypto_lib("Signing failed"); //@ open principal(principal1, count1 + 1); //@ open cryptogram(output, ?sig_length, ?sig_cs, ?sig_cg); //@ assert sig_cg == cg_asym_signature(principal, count, pay_cs, ?ent); //@ assert u_integer(&olen, sig_length); //@ assert sig_length > 0 &*& sig_length <= RSA_KEY_SIZE; nonces_hide_state(random_state); //@ pk_release_context_with_key(&context); pk_free(&context); //@ open pk_context(&context); //@ close [f]world(pub, key_clsfy); debug_print("signed item\n"); print_buffer(output, (int) olen); // Create item if (olen < MINIMAL_STRING_SIZE) abort_crypto_lib("Assymetric signing failed: output to small"); result->size = TAG_LENGTH + (int) olen; result->content = malloc(result->size); if (result->content == 0) {abort_crypto_lib("Malloc failed");} write_tag(result->content, TAG_ASYMMETRIC_SIG); //@ assert result->content |-> ?cont &*& result->size |-> ?size; //@ assert chars(cont, TAG_LENGTH, ?tag_cs); //@ assert tag_cs == full_tag(TAG_ASYMMETRIC_SIG); //@ public_chars(cont, TAG_LENGTH); //@ chars_to_secret_crypto_chars(cont, TAG_LENGTH); memcpy(result->content + TAG_LENGTH, output, olen); //@ crypto_chars_join(cont); //@ list<char> cs = append(tag_cs, sig_cs); //@ assert crypto_chars(secret, cont, size, cs); //@ item e = asymmetric_signature_item(principal, count, some(pay), ent); //@ close ic_cg(e)(sig_cs, sig_cg); /*@ if (col) { public_chars(cont, size); public_generated_split(polarssl_pub(pub), cs, TAG_LENGTH); } @*/ //@ close item(payload, pay, pub); zeroize(output, (int) olen); //@ chars_join(output); free(output); //@ WELL_FORMED(tag_cs, sig_cs, TAG_ASYMMETRIC_SIG) //@ close ic_parts(e)(tag_cs, sig_cs); //@ close well_formed_item_chars(e)(pay_cs); //@ leak well_formed_item_chars(e)(pay_cs); //@ close item_constraints(e, cs, pub); //@ leak item_constraints(e, cs, pub); //@ close item(result, e, pub); } debug_print("SINGING RESULT:\n"); print_item(result); return result; }
struct item *create_pair(struct item *first, struct item *second) /*@ requires [?f0]world(?pub, ?key_clsfy) &*& [?f1]item(first, ?f, pub) &*& [?f2]item(second, ?s, pub); @*/ /*@ ensures [f0]world(pub, key_clsfy) &*& [f1]item(first, f, pub) &*& [f2]item(second, s, pub) &*& item(result, pair_item(f, s), pub); @*/ { //@ open [f0]world(pub, key_clsfy); struct item* pair = malloc(sizeof(struct item)); if (pair == 0){abort_crypto_lib("malloc of item failed");} //@ open [f1]item(first, f, pub); //@ assert [f1]first->content |-> ?cont_f &*& [f1]first->size |-> ?size_f; //@ assert [f1]crypto_chars(secret, cont_f, size_f, ?cs_f); //@ assert [_]item_constraints(f, cs_f, pub); //@ well_formed_item_constraints(f, f); //@ open [_]well_formed_item_chars(f)(cs_f); //@ open [f2]item(second, s, pub); //@ assert [f2]second->content |-> ?cont_s &*& [f2]second->size |-> ?size_s; //@ assert [f2]crypto_chars(secret, cont_s, size_s, ?cs_s); //@ well_formed_item_constraints(s, s); //@ open [_]well_formed_item_chars(s)(cs_s); //@ assert [_]item_constraints(s, cs_s, pub); if (INT_MAX - TAG_LENGTH - (int) sizeof(int) - first->size < second->size) abort_crypto_lib("Requested pair item was to big"); pair->size = TAG_LENGTH + (int) sizeof(int) + first->size + second->size; pair->content = malloc_wrapper(pair->size); //@ assert pair->content |-> ?cont &*& pair->size |-> ?size; write_tag(pair->content, TAG_PAIR); { //@ assert chars(cont, TAG_LENGTH, full_tag(TAG_PAIR)); //@ public_chars(cont, TAG_LENGTH); //@ chars_to_secret_crypto_chars(cont, TAG_LENGTH); char* temp = pair->content + TAG_LENGTH; //@ chars_split(cont + TAG_LENGTH, sizeof(int)); //@ assert [f1]integer(&first->size, ?flen); //@ integer_to_chars(&first->size); //@ open chars((void*) &first->size, sizeof(int), chars_of_int(flen)); //@ character_limits((void*) &first->size); //@ close [f1]chars((void*) &first->size, sizeof(int), chars_of_int(flen)); //@ public_chars((void*) &first->size, sizeof(int)); //@ public_chars((void*) &first->size, sizeof(int)); //@ chars_to_crypto_chars((void*) &first->size, sizeof(int)); write_buffer(&temp, (void*) &(first->size), (int) sizeof(int)); //@ crypto_chars_to_chars((void*) &first->size, sizeof(int)); //@ chars_to_secret_crypto_chars(temp - sizeof(int), sizeof(int)); //@ chars_to_integer(&first->size); //@ chars_split(cont + TAG_LENGTH + sizeof(int), first->size); write_buffer(&temp, first->content, first->size); write_buffer(&temp, second->content, second->size); //@ crypto_chars_join(cont + TAG_LENGTH + sizeof(int)); //@ crypto_chars_join(cont + TAG_LENGTH); //@ crypto_chars_join(cont); } //@ list<char> size_f_cs = chars_of_int(size_f); //@ list<char> cs0 = append(size_f_cs, append(cs_f, cs_s)); //@ list<char> cs = append(full_tag(TAG_PAIR), cs0); //@ take_append(TAG_LENGTH, full_tag(TAG_PAIR), cs0); //@ drop_append(TAG_LENGTH, full_tag(TAG_PAIR), cs0); //@ assert length(size_f_cs) == sizeof(int); //@ take_append(sizeof(int), size_f_cs, append(cs_f, cs_s)); //@ drop_append(sizeof(int), size_f_cs, append(cs_f, cs_s)); //@ take_append(size_f, cs_f, cs_s); //@ drop_append(size_f, cs_f, cs_s); //@ assert drop(sizeof(int), cs0) == append(cs_f, cs_s); //@ assert size_f_cs == chars_of_unbounded_int(length(cs_f)); //@ append_assoc(size_f_cs, cs_f, cs_s); //@ assert crypto_chars(secret, cont, size, cs); //@ item p = pair_item(f, s); //@ close ic_pair(p)(cs_f, cs_s); //@ length_equals_nat_length(cs); //@ length_equals_nat_length(cs0); //@ drop_drop(sizeof(int), TAG_LENGTH, cs); //@ head_append(full_tag(TAG_PAIR), cs0); /*@ switch(nat_length(cs)) { case succ(n): well_formed_upper_bound(cs_f, nat_length(cs_f), n); well_formed_upper_bound(cs_s, nat_length(cs_s), n); case zero: assert false; } @*/ /*@ if(col) { public_chars(cont, size); public_generated_split(polarssl_pub(pub), cs, TAG_LENGTH); } @*/ //@ close ic_parts(p)(full_tag(TAG_PAIR), cs0); //@ close item_constraints(p, cs, pub); //@ leak item_constraints(p, cs, pub); //@ close item(pair, p, pub); //@ close [f1]item(first, f, pub); //@ close [f2]item(second, s, pub); return pair; //@ close [f0]world(pub, key_clsfy); }
void asymmetric_signature_verify(struct item *key, struct item *item, struct item *signature) /*@ requires [?f]world(?pub, ?key_clsfy) &*& item(item, ?i, pub) &*& item(key, ?k, pub) &*& item(signature, ?sig, pub) &*& sig == asymmetric_signature_item(?principal1, ?count1, ?pay1, ?ent) &*& k == public_key_item(?principal2, ?count2); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& item(item, i, pub) &*& item(key, k, pub) &*& item(signature, sig, pub) &*& switch(pay1) { case some(pay2): return col || (principal1 == principal2 && count1 == count2 && i == pay2); case none: return true == col; }; @*/ { debug_print("ASYM SIGNATURE CHECKING:\n"); print_item(signature); check_is_asymmetric_signature(signature); { pk_context context; unsigned int olen; char* output; // Key //@ close pk_context(&context); //@ open [f]world(pub, key_clsfy); pk_init(&context); //@ close [f]world(pub, key_clsfy); set_public_key(&context, key); /*@ assert pk_context_with_key(&context, pk_public, ?principal3, ?count3, RSA_BIT_KEY_SIZE); @*/ // Signature checking //@ open item(item, ?i_old, pub); //@ assert item->content |-> ?i_cont &*& item->size |-> ?i_size; //@ assert crypto_chars(secret, i_cont, i_size, ?i_cs); //@ assert [_]item_constraints(i, i_cs, pub); //@ open item(signature, _, pub); //@ assert signature->content |-> ?s_cont &*& signature->size |-> ?s_size; //@ assert crypto_chars(secret, s_cont, s_size, ?sig_cs); //@ open [_]item_constraints(sig, sig_cs, pub); //@ open ic_parts(sig)(?sig_tag, ?sig_cont); //@ take_append(TAG_LENGTH, sig_tag, sig_cont); //@ drop_append(TAG_LENGTH, sig_tag, sig_cont); //@ open [_]ic_cg(sig)(_, ?cg_sig); //@ assert cg_sig == cg_asym_signature(principal1, count1, ?cs_pay, ent); if (item->size > RSA_KEY_SIZE) abort_crypto_lib("Assymetric signature checking failed: incorrect sizes"); //@ crypto_chars_limits(s_cont); //@ crypto_chars_split(s_cont, TAG_LENGTH); //@ assert crypto_chars(secret, s_cont, TAG_LENGTH, sig_tag); //@ assert crypto_chars(secret, s_cont + TAG_LENGTH, ?s, sig_cont); //@ assert s == s_size - TAG_LENGTH; //@ if (col) cg_sig = chars_for_cg_sur(sig_cont, tag_asym_signature); //@ if (col) crypto_chars_to_chars(s_cont + TAG_LENGTH, s); //@ if (col) public_chars_extract(s_cont + TAG_LENGTH, cg_sig); //@ if (col) chars_to_secret_crypto_chars(s_cont + TAG_LENGTH, s); //@ close cryptogram(s_cont + TAG_LENGTH, s, sig_cont, cg_sig); if(pk_verify(&context, POLARSSL_MD_NONE, item->content, (unsigned int) item->size, signature->content + TAG_LENGTH, (unsigned int) (signature->size - TAG_LENGTH)) != 0) abort_crypto_lib("Signing check failed: signature" "was not created with the provided key"); //@ pk_release_context_with_key(&context); pk_free(&context); //@ open pk_context(&context); //@ open cryptogram(s_cont + TAG_LENGTH, s, sig_cont, cg_sig); //@ crypto_chars_join(s_cont); //@ close item(signature, sig, pub); /*@ if (!col) { assert principal2 == principal3; assert count2 == count3; assert cs_pay == i_cs; open [_]item_constraints(i, cs_pay, pub); switch(pay1) { case some(pay2): assert [_]item_constraints(pay2, cs_pay, pub); item_constraints_injective(i, pay2, cs_pay); case none: open [_]ill_formed_item_chars(sig)(cs_pay); assert false; } } @*/ //@ close item(item, i, pub); } }