security/manager/ssl/src/nsDataSignatureVerifier.cpp

branch
TOR_BUG_9701
changeset 3
141e0f1194b1
equal deleted inserted replaced
-1:000000000000 0:c3a111537bab
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "nsDataSignatureVerifier.h"
6 #include "nsCOMPtr.h"
7 #include "nsString.h"
8
9 #include "seccomon.h"
10 #include "nssb64.h"
11 #include "certt.h"
12 #include "keyhi.h"
13 #include "cryptohi.h"
14
15 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
16
17 NS_IMPL_ISUPPORTS(nsDataSignatureVerifier, nsIDataSignatureVerifier)
18
19 const SEC_ASN1Template CERT_SignatureDataTemplate[] =
20 {
21 { SEC_ASN1_SEQUENCE,
22 0, nullptr, sizeof(CERTSignedData) },
23 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
24 offsetof(CERTSignedData,signatureAlgorithm),
25 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), },
26 { SEC_ASN1_BIT_STRING,
27 offsetof(CERTSignedData,signature), },
28 { 0, }
29 };
30
31 NS_IMETHODIMP
32 nsDataSignatureVerifier::VerifyData(const nsACString & aData,
33 const nsACString & aSignature,
34 const nsACString & aPublicKey,
35 bool *_retval)
36 {
37 // Allocate an arena to handle the majority of the allocations
38 PLArenaPool *arena;
39 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
40 if (!arena)
41 return NS_ERROR_OUT_OF_MEMORY;
42
43 // Base 64 decode the key
44 SECItem keyItem;
45 PORT_Memset(&keyItem, 0, sizeof(SECItem));
46 if (!NSSBase64_DecodeBuffer(arena, &keyItem,
47 nsPromiseFlatCString(aPublicKey).get(),
48 aPublicKey.Length())) {
49 PORT_FreeArena(arena, false);
50 return NS_ERROR_FAILURE;
51 }
52
53 // Extract the public key from the data
54 CERTSubjectPublicKeyInfo *pki = SECKEY_DecodeDERSubjectPublicKeyInfo(&keyItem);
55 if (!pki) {
56 PORT_FreeArena(arena, false);
57 return NS_ERROR_FAILURE;
58 }
59 SECKEYPublicKey *publicKey = SECKEY_ExtractPublicKey(pki);
60 SECKEY_DestroySubjectPublicKeyInfo(pki);
61 pki = nullptr;
62
63 if (!publicKey) {
64 PORT_FreeArena(arena, false);
65 return NS_ERROR_FAILURE;
66 }
67
68 // Base 64 decode the signature
69 SECItem signatureItem;
70 PORT_Memset(&signatureItem, 0, sizeof(SECItem));
71 if (!NSSBase64_DecodeBuffer(arena, &signatureItem,
72 nsPromiseFlatCString(aSignature).get(),
73 aSignature.Length())) {
74 SECKEY_DestroyPublicKey(publicKey);
75 PORT_FreeArena(arena, false);
76 return NS_ERROR_FAILURE;
77 }
78
79 // Decode the signature and algorithm
80 CERTSignedData sigData;
81 PORT_Memset(&sigData, 0, sizeof(CERTSignedData));
82 SECStatus ss = SEC_QuickDERDecodeItem(arena, &sigData,
83 CERT_SignatureDataTemplate,
84 &signatureItem);
85 if (ss != SECSuccess) {
86 SECKEY_DestroyPublicKey(publicKey);
87 PORT_FreeArena(arena, false);
88 return NS_ERROR_FAILURE;
89 }
90
91 // Perform the final verification
92 DER_ConvertBitString(&(sigData.signature));
93 ss = VFY_VerifyDataWithAlgorithmID((const unsigned char*)nsPromiseFlatCString(aData).get(),
94 aData.Length(), publicKey,
95 &(sigData.signature),
96 &(sigData.signatureAlgorithm),
97 nullptr, nullptr);
98
99 // Clean up remaining objects
100 SECKEY_DestroyPublicKey(publicKey);
101 PORT_FreeArena(arena, false);
102
103 *_retval = (ss == SECSuccess);
104
105 return NS_OK;
106 }

mercurial