1
//! Macros that we use to define other types in this crate.
2
//!
3
//! (These macros are not likely to work outside of the context used in this
4
//! crate without additional help.)
5

            
6
/// Define a public key type and a private key type to wrap a given inner key.
7
//
8
// TODO This macro needs proper formal documentation of its its input syntax and semantics.
9
// (Possibly the input syntax ought to be revisited.)
10
macro_rules! define_pk_keypair {
11
    {
12
        $(#[$meta:meta])* pub struct $pk:ident($pkt:ty) / $(#[$sk_meta:meta])* $sk:ident($skt:ty);
13
        $($(#[$p_meta:meta])* curve25519_pair as $pair:ident;)?
14
    } => {
15
        paste::paste!{
16
            $(#[$meta])*
17
            #[derive(Clone,Debug,derive_more::From,derive_more::Deref,derive_more::Into,derive_more::AsRef)]
18
3120
            pub struct $pk ($pkt);
19
3120

            
20
3120
            #[doc = concat!("The private counterpart of a [`", stringify!($pk), "`].")]
21
3120
            $(#[$sk_meta])*
22
3120
            #[derive(derive_more::From, derive_more::Into, derive_more::AsRef)]
23
3120
            pub struct $sk ($skt);
24
520

            
25
520
            impl std::fmt::Debug for $sk
26
520
            {
27
1560
                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28
1560
                    f.write_str(concat!(stringify!($pk), "SecretKey(...)"))
29
1560
                }
30
520
            }
31
520

            
32
520
            // For curve25519 keys, we are willing to handle secret keys without
33
520
            // a corresponding public key, since there is not a cryptographic
34
520
            // risk inherent in our protocols to getting them mixed up.
35
520
            //
36
520
            // But that means that it sometimes _is_ worthwhile defining a
37
520
            // keypair type.
38
520
            $(
39
520
                #[doc = concat!("A pair of a public and private components for a [`", stringify!($pk), "`].")]
40
520
                $(#[$p_meta])*
41
520
                #[derive(Debug)]
42
520
                pub struct $pair {
43
520
                    public: $pk,
44
520
                    secret: $sk,
45
520
                }
46
520
                impl $pair {
47
520
                    /// Construct this keypair from a public key and a secret key.
48
1625
                    pub fn new(public: $pk, secret: $sk) -> Self {
49
1625
                        Self { public, secret }
50
1625
                    }
51
520
                    /// Construct this keypair from a secret key.
52
520
                    pub fn from_secret_key(secret: $sk) -> Self {
53
520
                        let public:$pk = $pkt::from(&secret.0).into();
54
520
                        Self { public, secret }
55
520
                    }
56
3120
                    /// Return the public part of this keypair.
57
3120
                    pub fn public(&self) -> &$pk { &self.public }
58
520
                    /// Return the secret part of this keypair.
59
520
                    pub fn secret(&self) -> &$sk { &self.secret }
60
                    /// Generate a new keypair from a secure random number generator.
61
                    //
62
                    // TODO: this should be implemented in terms of
63
                    // `<curve25519::StaticSecret as tor_keymgr::Keygen>` and
64
                    // `<$pair as From<curve25519::StaticKeypair>>`
65
                    // See https://gitlab.torproject.org/tpo/core/arti/-/issues/1137#note_2969181
66
42
                    pub fn generate<R>(rng: &mut R) -> Self
67
42
                    where
68
42
                        R: rand::Rng + rand::CryptoRng,
69
                    {
70
42
                        let secret = curve25519::StaticSecret::random_from_rng(rng);
71
42
                        let public: curve25519::PublicKey = (&secret).into();
72
42
                        Self {
73
42
                            secret: secret.into(),
74
42
                            public: public.into(),
75
42
                        }
76
42
                    }
77
                }
78
                impl From<curve25519::StaticKeypair> for $pair {
79
3250
                    fn from(input: curve25519::StaticKeypair) -> $pair {
80
3250
                        $pair {
81
3250
                            secret: input.secret.into(),
82
3250
                            public: input.public.into(),
83
3250
                        }
84
3250
                    }
85
                }
86
                impl From<$pair> for curve25519::StaticKeypair {
87
1040
                    fn from(input: $pair) -> curve25519::StaticKeypair {
88
1040
                        curve25519::StaticKeypair {
89
1040
                            secret: input.secret.into(),
90
1040
                            public: input.public.into(),
91
1040
                        }
92
1040
                    }
93
                }
94
            )?
95
        }
96
    };
97
}
98

            
99
/// Define a wrapper type around a byte array of fixed length.
100
///
101
/// (Internally, it uses a [`CtByteArray`](tor_llcrypto::util::ct::CtByteArray),
102
/// so it's safe to derive Ord, Eq, etc.)
103
macro_rules! define_bytes {
104
{ $(#[$meta:meta])* pub struct $name:ident([u8 ; $n:expr]); } =>
105
{
106
    $(#[$meta])*
107
    pub struct $name(tor_llcrypto::util::ct::CtByteArray<$n>);
108

            
109
    impl $name {
110
10867
        fn new(inp: [u8;$n]) -> Self {
111
10867
            Self(inp.into())
112
10867
        }
113
    }
114
    impl AsRef<[u8;$n]> for $name {
115
30430
        fn as_ref(&self) -> &[u8;$n] {
116
30430
            self.0.as_ref()
117
30430
        }
118
    }
119
    impl From<[u8;$n]> for $name {
120
10607
        fn from(inp: [u8;$n]) -> Self {
121
10607
            Self::new(inp)
122
10607
        }
123
    }
124
    impl From<$name> for [u8;$n] {
125
        fn from(inp: $name) -> [u8;$n] {
126
            inp.0.into()
127
        }
128
    }
129
    impl tor_bytes::Readable for $name {
130
325
        fn take_from(r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
131
325
            Ok(Self::new(r.extract()?))
132
325
        }
133
    }
134
    impl tor_bytes::Writeable for $name {
135
20
        fn write_onto<B:tor_bytes::Writer+?Sized>(&self, w: &mut B) -> tor_bytes::EncodeResult<()> {
136
20
            w.write_all(&self.0.as_ref()[..]);
137
20
            Ok(())
138
20
        }
139
    }
140
}
141
}
142

            
143
pub(crate) use {define_bytes, define_pk_keypair};