1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef dtls_identity_h__
7 #define dtls_identity_h__
8 
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "ScopedNSSTypes.h"
14 #include "m_cpp_utils.h"
15 #include "mozilla/RefPtr.h"
16 #include "nsISupportsImpl.h"
17 #include "nsTArray.h"
18 #include "sslt.h"
19 
20 // All code in this module requires NSS to be live.
21 // Callers must initialize NSS and implement the nsNSSShutdownObject
22 // protocol.
23 namespace mozilla {
24 
25 class DtlsDigest {
26  public:
27   const static size_t kMaxDtlsDigestLength = HASH_LENGTH_MAX;
28   DtlsDigest() = default;
DtlsDigest(const std::string & algorithm)29   explicit DtlsDigest(const std::string& algorithm) : algorithm_(algorithm) {}
DtlsDigest(const std::string & algorithm,const std::vector<uint8_t> & value)30   DtlsDigest(const std::string& algorithm, const std::vector<uint8_t>& value)
31       : algorithm_(algorithm), value_(value) {
32     MOZ_ASSERT(value.size() <= kMaxDtlsDigestLength);
33   }
34   ~DtlsDigest() = default;
35 
36   bool operator!=(const DtlsDigest& rhs) const { return !operator==(rhs); }
37 
38   bool operator==(const DtlsDigest& rhs) const {
39     if (algorithm_ != rhs.algorithm_) {
40       return false;
41     }
42 
43     return value_ == rhs.value_;
44   }
45 
46   std::string algorithm_;
47   std::vector<uint8_t> value_;
48 };
49 
50 typedef std::vector<DtlsDigest> DtlsDigestList;
51 
52 class DtlsIdentity final {
53  public:
54   // This constructor takes ownership of privkey and cert.
DtlsIdentity(UniqueSECKEYPrivateKey privkey,UniqueCERTCertificate cert,SSLKEAType authType)55   DtlsIdentity(UniqueSECKEYPrivateKey privkey, UniqueCERTCertificate cert,
56                SSLKEAType authType)
57       : private_key_(std::move(privkey)),
58         cert_(std::move(cert)),
59         auth_type_(authType) {}
60 
61   // Allows serialization/deserialization; cannot write IPC serialization code
62   // directly for DtlsIdentity, since IPC-able types need to be constructable
63   // on the stack.
64   nsresult Serialize(nsTArray<uint8_t>* aKeyDer, nsTArray<uint8_t>* aCertDer);
65   static RefPtr<DtlsIdentity> Deserialize(const nsTArray<uint8_t>& aKeyDer,
66                                           const nsTArray<uint8_t>& aCertDer,
67                                           SSLKEAType authType);
68 
69   // This is only for use in tests, or for external linkage.  It makes a (bad)
70   // instance of this class.
71   static RefPtr<DtlsIdentity> Generate();
72 
73   // These don't create copies or transfer ownership. If you want these to live
74   // on, make a copy.
cert()75   const UniqueCERTCertificate& cert() const { return cert_; }
privkey()76   const UniqueSECKEYPrivateKey& privkey() const { return private_key_; }
77   // Note: this uses SSLKEAType because that is what the libssl API requires.
78   // This is a giant confusing mess, but libssl indexes certificates based on a
79   // key exchange type, not authentication type (as you might have reasonably
80   // expected).
auth_type()81   SSLKEAType auth_type() const { return auth_type_; }
82 
83   nsresult ComputeFingerprint(DtlsDigest* digest) const;
84   static nsresult ComputeFingerprint(const UniqueCERTCertificate& cert,
85                                      DtlsDigest* digest);
86 
87   static const std::string DEFAULT_HASH_ALGORITHM;
88   enum { HASH_ALGORITHM_MAX_LENGTH = 64 };
89 
90   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DtlsIdentity)
91 
92  private:
93   ~DtlsIdentity() = default;
94   DISALLOW_COPY_ASSIGN(DtlsIdentity);
95 
96   UniqueSECKEYPrivateKey private_key_;
97   UniqueCERTCertificate cert_;
98   SSLKEAType auth_type_;
99 };
100 }  // namespace mozilla
101 #endif
102