1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! V1 advertisement section np_ed25519 signature payload 16 //! after the included context bytes, and utilities for 17 //! performing signatures and signature verification. 18 19 use crate::header::VERSION_HEADER_V1; 20 use crypto_provider::{ 21 aes::ctr::AesCtrNonce, 22 ed25519::{Ed25519Provider, PrivateKey, PublicKey, Signature}, 23 }; 24 use sink::{Sink, SinkWriter}; 25 26 use crate::NP_SVC_UUID; 27 28 /// A struct representing the necessary contents 29 /// of an v1 advertisement section np_ed25519 signature payload which 30 /// come after the context prefix (shared among all advs). 31 pub(crate) struct SectionSignaturePayload<'a> { 32 /// first 1-2 bytes of format 33 format_bytes: &'a [u8], 34 /// Salt bytes 35 salt_bytes: &'a [u8], 36 /// Nonce for en/decrypting the section 37 nonce: &'a AesCtrNonce, 38 /// plaintext identity token 39 plaintext_identity_token: &'a [u8], 40 /// the len of the rest of the section contents stored as an u8 41 section_payload_len: u8, 42 /// plaintext identity token 43 plaintext_data_elements: &'a [u8], 44 } 45 46 const ADV_SIGNATURE_CONTEXT: np_ed25519::SignatureContext = { 47 match np_ed25519::SignatureContext::from_string_bytes("Advertisement Signed Section") { 48 Ok(x) => x, 49 Err(_) => panic!(), 50 } 51 }; 52 53 impl<'a> SectionSignaturePayload<'a> { 54 /// Construct a section signature payload with separate section len and 55 /// remaining contents of the section header. 56 /// 57 /// The section header should be in its on-the-wire form. new( format_bytes: &'a [u8], salt_bytes: &'a [u8], nonce: &'a AesCtrNonce, plaintext_identity_token: &'a [u8], section_payload_len: u8, plaintext_data_elements: &'a [u8], ) -> Self58 pub(crate) fn new( 59 format_bytes: &'a [u8], 60 salt_bytes: &'a [u8], 61 nonce: &'a AesCtrNonce, 62 plaintext_identity_token: &'a [u8], 63 section_payload_len: u8, 64 plaintext_data_elements: &'a [u8], 65 ) -> Self { 66 Self { 67 format_bytes, 68 salt_bytes, 69 nonce, 70 plaintext_identity_token, 71 section_payload_len, 72 plaintext_data_elements, 73 } 74 } 75 76 /// Generates a signature for this section signing payload using 77 /// the given Ed25519 key-pair. sign<E: Ed25519Provider>(self, private_key: &PrivateKey) -> Signature78 pub(crate) fn sign<E: Ed25519Provider>(self, private_key: &PrivateKey) -> Signature { 79 np_ed25519::sign_with_context::<E, _>(private_key, &ADV_SIGNATURE_CONTEXT, self) 80 .expect("section signature payloads should fit in signature buffer") 81 } 82 83 /// Verifies a signature for this section signing payload using 84 /// the given Ed25519 public key. verify<E: Ed25519Provider>( self, signature: Signature, public_key: &PublicKey, ) -> Result<(), np_ed25519::SignatureVerificationError>85 pub(crate) fn verify<E: Ed25519Provider>( 86 self, 87 signature: Signature, 88 public_key: &PublicKey, 89 ) -> Result<(), np_ed25519::SignatureVerificationError> { 90 np_ed25519::verify_signature_with_context::<E, _>( 91 public_key, 92 &ADV_SIGNATURE_CONTEXT, 93 self, 94 signature, 95 ) 96 } 97 } 98 99 impl<'a> SinkWriter for SectionSignaturePayload<'a> { 100 type DataType = u8; 101 write_payload<S: Sink<u8> + ?Sized>(self, sink: &mut S) -> Option<()>102 fn write_payload<S: Sink<u8> + ?Sized>(self, sink: &mut S) -> Option<()> { 103 sink.try_extend_from_slice(&NP_SVC_UUID)?; 104 sink.try_push(VERSION_HEADER_V1)?; 105 sink.try_extend_from_slice(self.format_bytes)?; 106 sink.try_extend_from_slice(self.salt_bytes)?; 107 sink.try_extend_from_slice(self.nonce)?; 108 sink.try_extend_from_slice(self.plaintext_identity_token)?; 109 sink.try_push(self.section_payload_len)?; 110 sink.try_extend_from_slice(self.plaintext_data_elements) 111 } 112 } 113