1 /*
2  *  livesig.h
3  *
4  *  Implements sign and verify functions using DNSSEC public keys using OpenSSL
5  *  if available.
6  *
7  *  Supports RSASHA1, and if OpenSSL is compiled with --enable-ec, ECDSAP256*
8  *  and ECDSAP384*
9  *
10  *  Also supports an OpenSSL less mode, which uses no crypto
11  *  (POPT_CONT_INT_PROT_NONE). To use it, compile without -DOPENSSL. In that
12  *  case the private key is a 1 random byte and the public key is that byte
13  *  repeated SWIFT_CIPM_NONE_KEYLEN times.
14  *
15  *  Created by Arno Bakker
16  *  Copyright 2013-2016 Vrije Universiteit Amsterdam. All rights reserved.
17  */
18 #ifndef SWIFT_LIVESIG_H_
19 #define SWIFT_LIVESIG_H_
20 
21 // Length of fake signature in SIGNED_INTEGRITY when Content Integrity Protection off
22 #define SWIFT_CIPM_NONE_KEYLEN  21  // bytes, must be larger than Sha1Hash::SIZE
23 #define SWIFT_CIPM_NONE_SIGLEN  20  // bytes
24 
25 
26 #ifdef OPENSSL
27 
28 #include <openssl/evp.h>
29 #include <openssl/rand.h>
30 
31 #else
32 
33 // Dummy funcs, so swift will compile for VOD and live with no CIPM without OpenSSL.
34 // When CIPM is NONE the private key is 1 byte and the public key is that byte
35 // repeated 21 times.
36 //
37 typedef uint8_t EVP_PKEY;
38 typedef int EVP_MD_CTX;
39 #define EVP_PKEY_free(x)
40 #define EVP_PKEY_size(x)    SWIFT_CIPM_NONE_SIGLEN
41 
42 #endif
43 
44 namespace swift
45 {
46 
47 // http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml
48     typedef enum {
49         POPT_LIVE_SIG_ALG_RSASHA1 = 5,
50         POPT_LIVE_SIG_ALG_ECDSAP256SHA256 = 13,
51         POPT_LIVE_SIG_ALG_ECDSAP384SHA384 = 14,
52         POPT_LIVE_SIG_ALG_PRIVATEDNS = 253
53     } popt_live_sig_alg_t;
54 
55 
56 // Arno, 2013-10-09: Gives nice short SwarmIDs
57 #define DEFAULT_LIVE_SIG_ALG    POPT_LIVE_SIG_ALG_ECDSAP256SHA256
58 
59 
60     /** Structure for holding a signature */
61     struct Signature {
62         uint8_t    *sigbits_;
63         uint16_t   siglen_;
SignatureSignature64         Signature() : sigbits_(NULL), siglen_(0)  {}
65         Signature(uint8_t *sb, uint16_t len);
66         Signature(bool hex, const uint8_t *sb, uint16_t len);
67         Signature(const Signature &copy);
68         Signature & operator = (const Signature &source);
69         ~Signature();
bitsSignature70         uint8_t  *bits()  {
71             return sigbits_;
72         }
lengthSignature73         uint16_t length() {
74             return siglen_;
75         }
76         std::string hex() const;
77 
78         const static Signature NOSIG;
79     };
80 
81 // Default keysize when using RSASHA1
82 #define SWIFT_RSA_DEFAULT_KEYSIZE   1024    // bits
83 
84 
85     struct SwarmPubKey;
86 
87 // Callback used when generating (RSA) keys, see https://www.openssl.org/docs/crypto/BN_generate_prime.html
88     typedef void (*simple_openssl_callback_t)(int);
89 
90 
91     /** Public/private (source) or just public key (client) for signing, and verification, resp. */
92     struct KeyPair {
93     public:
KeyPairKeyPair94         KeyPair() { // keep compiler happy
95             alg_ = POPT_LIVE_SIG_ALG_PRIVATEDNS;
96             evp_ = NULL;
97         }
KeyPairKeyPair98         KeyPair(popt_live_sig_alg_t alg,EVP_PKEY *evp) {
99             alg_ = alg;
100             evp_ = evp;
101         }
~KeyPairKeyPair102         ~KeyPair() {
103             if (evp_ != NULL)
104                 EVP_PKEY_free(evp_);
105             evp_ = NULL;
106 
107         }
108 
109         /** Create a new key pair, calling callback as the key is generated */
110         static KeyPair *Generate(popt_live_sig_alg_t alg, uint16_t keysize=SWIFT_RSA_DEFAULT_KEYSIZE,
111                                  simple_openssl_callback_t callback=NULL);
112 
113         /** For testing */
GetEVPKeyPair114         EVP_PKEY       *GetEVP() {
115             return evp_;
116         }
117 
118         /** Return PPSPP encoded public key = Algorithm byte + DNSSEC encoded public key */
119         SwarmPubKey    *GetSwarmPubKey();
120 
121         /** Returns a Signature with the private key over data */
122         Signature      *Sign(uint8_t *data, uint16_t datalength);
123 
124         /** Returns whether the Signature was made by the public key over data */
125         bool           Verify(uint8_t *data, uint16_t datalength,Signature &sig);
126 
127         /** Returns the DNSSEC signature algorithm used */
GetSigAlgKeyPair128         popt_live_sig_alg_t GetSigAlg() {
129             return alg_;
130         }
131 
132         /** Returns the number of bytes a signature takes on the wire */
133         uint16_t       GetSigSizeInBytes();
134 
135         /** Returns NULL on error. */
136         static KeyPair *ReadPrivateKey(std::string keypairfilename);
137         /** Returns -1 on error */
138         int            WritePrivateKey(std::string keypairfilename);
139 
140     protected:
141         popt_live_sig_alg_t alg_;
142         EVP_PKEY        *evp_;
143     };
144 
145 
146     /** -08: SwarmID for live streams is an Algorithm Byte followed by a public key
147      * encoded as in a DNSSEC DNSKEY resource record without BASE-64 encoding.
148      */
149     struct SwarmPubKey {
150     public:
SwarmPubKeySwarmPubKey151         SwarmPubKey() : bits_(NULL), len_(0)  {}
152         SwarmPubKey(uint8_t *bits, uint16_t len);
153         SwarmPubKey(const SwarmPubKey& copy);
154         SwarmPubKey(std::string hexstr);
155         ~SwarmPubKey();
156         SwarmPubKey & operator = (const SwarmPubKey &source);
157         bool     operator == (const SwarmPubKey& b) const;
bitsSwarmPubKey158         uint8_t  *bits()  {
159             return bits_;
160         }
lengthSwarmPubKey161         uint16_t length() {
162             return len_;
163         }
164         std::string hex() const;
165         KeyPair  *GetPublicKeyPair() const;
166 
167         const static SwarmPubKey NOSPUBKEY;
168     protected:
169         uint8_t *bits_;
170         uint16_t    len_;
171     };
172 
173 }
174 
175 #endif /* SWIFT_LIVESIG_H_ */
176