/*---------------------------------------------------------------------------*/ static int create(void) { int result; result = DECORATED_FRAMER.create(); if(result == FRAMER_FAILED) { return result; } aead(result, 1); return result; }
/*---------------------------------------------------------------------------*/ static int create(void) { int result; add_security_header(); result = framer_802154.create(); if(result == FRAMER_FAILED) { return result; } aead(result, 1); return result; }
secure_vector<byte> mceies_decrypt(const McEliece_PrivateKey& privkey, const byte ct[], size_t ct_len, const byte ad[], size_t ad_len, const std::string& algo) { try { McEliece_KEM_Decryptor kem_op(privkey); const size_t mce_code_bytes = (privkey.get_code_length() + 7) / 8; std::unique_ptr<AEAD_Mode> aead(get_aead(algo, DECRYPTION)); if(!aead) throw std::runtime_error("Unable to create AEAD instance '" + algo + "'"); const size_t nonce_len = aead->default_nonce_length(); if(ct_len < mce_code_bytes + nonce_len + aead->tag_size()) throw std::runtime_error("Input message too small to be valid"); const secure_vector<byte> mce_key = kem_op.decrypt(ct, mce_code_bytes); aead->set_key(aead_key(mce_key, *aead)); aead->set_associated_data(ad, ad_len); secure_vector<byte> pt(ct + mce_code_bytes + nonce_len, ct + ct_len); aead->start(&ct[mce_code_bytes], nonce_len); aead->finish(pt, 0); return pt; } catch(std::exception& e) { throw std::runtime_error("mce_decrypt failed: " + std::string(e.what())); } }
secure_vector<byte> mceies_encrypt(const McEliece_PublicKey& pubkey, const byte pt[], size_t pt_len, const byte ad[], size_t ad_len, RandomNumberGenerator& rng, const std::string& algo) { McEliece_KEM_Encryptor kem_op(pubkey); const std::pair<secure_vector<byte>,secure_vector<byte>> mce_ciphertext__key = kem_op.encrypt(rng); const secure_vector<byte>& mce_ciphertext = mce_ciphertext__key.first; const secure_vector<byte>& mce_key = mce_ciphertext__key.second; const size_t mce_code_bytes = (pubkey.get_code_length() + 7) / 8; BOTAN_ASSERT(mce_ciphertext.size() == mce_code_bytes, "Unexpected size"); std::unique_ptr<AEAD_Mode> aead(get_aead(algo, ENCRYPTION)); if(!aead) throw std::runtime_error("mce_encrypt unable to create AEAD instance '" + algo + "'"); const size_t nonce_len = aead->default_nonce_length(); aead->set_key(aead_key(mce_key, *aead)); aead->set_associated_data(ad, ad_len); const secure_vector<byte> nonce = rng.random_vec(nonce_len); secure_vector<byte> msg(mce_ciphertext.size() + nonce.size() + pt_len); copy_mem(msg.data(), mce_ciphertext.data(), mce_ciphertext.size()); copy_mem(msg.data() + mce_ciphertext.size(), nonce.data(), nonce.size()); copy_mem(msg.data() + mce_ciphertext.size() + nonce.size(), pt, pt_len); aead->start(nonce); aead->finish(msg, mce_ciphertext.size() + nonce.size()); return msg; }
/*---------------------------------------------------------------------------*/ static int parse(void) { int result; const linkaddr_t *sender; struct anti_replay_info* info; result = DECORATED_FRAMER.parse(); if(result == FRAMER_FAILED) { return result; } if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != SEC_LVL) { PRINTF("noncoresec: received frame with wrong security level\n"); return FRAMER_FAILED; } sender = packetbuf_addr(PACKETBUF_ADDR_SENDER); if(linkaddr_cmp(sender, &linkaddr_node_addr)) { PRINTF("noncoresec: frame from ourselves\n"); return FRAMER_FAILED; } packetbuf_set_datalen(packetbuf_datalen() - MIC_LEN); if(!aead(result, 0)) { PRINTF("noncoresec: received unauthentic frame %lu\n", anti_replay_get_counter()); return FRAMER_FAILED; } info = nbr_table_get_from_lladdr(anti_replay_table, sender); if(!info) { info = nbr_table_add_lladdr(anti_replay_table, sender, NBR_TABLE_REASON_LLSEC, NULL); if(!info) { PRINTF("noncoresec: could not get nbr_table_item\n"); return FRAMER_FAILED; } /* * Locking avoids replay attacks due to removed neighbor table items. * Unfortunately, an attacker can mount a memory-based DoS attack * on this by replaying broadcast frames from other network parts. * However, this is not an issue as long as the network size does not * exceed NBR_TABLE_MAX_NEIGHBORS. * * To avoid locking, we could swap anti-replay information * to external flash. Locking is also unnecessary when using * pairwise session keys, as done in coresec. */ if(!nbr_table_lock(anti_replay_table, info)) { nbr_table_remove(anti_replay_table, info); PRINTF("noncoresec: could not lock\n"); return FRAMER_FAILED; } anti_replay_init_info(info); } else { if(anti_replay_was_replayed(info)) { PRINTF("noncoresec: received replayed frame %lu\n", anti_replay_get_counter()); return FRAMER_FAILED; } } return result; }