1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/src/nsDataSignatureVerifier.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,106 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsDataSignatureVerifier.h" 1.9 +#include "nsCOMPtr.h" 1.10 +#include "nsString.h" 1.11 + 1.12 +#include "seccomon.h" 1.13 +#include "nssb64.h" 1.14 +#include "certt.h" 1.15 +#include "keyhi.h" 1.16 +#include "cryptohi.h" 1.17 + 1.18 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1.19 + 1.20 +NS_IMPL_ISUPPORTS(nsDataSignatureVerifier, nsIDataSignatureVerifier) 1.21 + 1.22 +const SEC_ASN1Template CERT_SignatureDataTemplate[] = 1.23 +{ 1.24 + { SEC_ASN1_SEQUENCE, 1.25 + 0, nullptr, sizeof(CERTSignedData) }, 1.26 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.27 + offsetof(CERTSignedData,signatureAlgorithm), 1.28 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), }, 1.29 + { SEC_ASN1_BIT_STRING, 1.30 + offsetof(CERTSignedData,signature), }, 1.31 + { 0, } 1.32 +}; 1.33 + 1.34 +NS_IMETHODIMP 1.35 +nsDataSignatureVerifier::VerifyData(const nsACString & aData, 1.36 + const nsACString & aSignature, 1.37 + const nsACString & aPublicKey, 1.38 + bool *_retval) 1.39 +{ 1.40 + // Allocate an arena to handle the majority of the allocations 1.41 + PLArenaPool *arena; 1.42 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.43 + if (!arena) 1.44 + return NS_ERROR_OUT_OF_MEMORY; 1.45 + 1.46 + // Base 64 decode the key 1.47 + SECItem keyItem; 1.48 + PORT_Memset(&keyItem, 0, sizeof(SECItem)); 1.49 + if (!NSSBase64_DecodeBuffer(arena, &keyItem, 1.50 + nsPromiseFlatCString(aPublicKey).get(), 1.51 + aPublicKey.Length())) { 1.52 + PORT_FreeArena(arena, false); 1.53 + return NS_ERROR_FAILURE; 1.54 + } 1.55 + 1.56 + // Extract the public key from the data 1.57 + CERTSubjectPublicKeyInfo *pki = SECKEY_DecodeDERSubjectPublicKeyInfo(&keyItem); 1.58 + if (!pki) { 1.59 + PORT_FreeArena(arena, false); 1.60 + return NS_ERROR_FAILURE; 1.61 + } 1.62 + SECKEYPublicKey *publicKey = SECKEY_ExtractPublicKey(pki); 1.63 + SECKEY_DestroySubjectPublicKeyInfo(pki); 1.64 + pki = nullptr; 1.65 + 1.66 + if (!publicKey) { 1.67 + PORT_FreeArena(arena, false); 1.68 + return NS_ERROR_FAILURE; 1.69 + } 1.70 + 1.71 + // Base 64 decode the signature 1.72 + SECItem signatureItem; 1.73 + PORT_Memset(&signatureItem, 0, sizeof(SECItem)); 1.74 + if (!NSSBase64_DecodeBuffer(arena, &signatureItem, 1.75 + nsPromiseFlatCString(aSignature).get(), 1.76 + aSignature.Length())) { 1.77 + SECKEY_DestroyPublicKey(publicKey); 1.78 + PORT_FreeArena(arena, false); 1.79 + return NS_ERROR_FAILURE; 1.80 + } 1.81 + 1.82 + // Decode the signature and algorithm 1.83 + CERTSignedData sigData; 1.84 + PORT_Memset(&sigData, 0, sizeof(CERTSignedData)); 1.85 + SECStatus ss = SEC_QuickDERDecodeItem(arena, &sigData, 1.86 + CERT_SignatureDataTemplate, 1.87 + &signatureItem); 1.88 + if (ss != SECSuccess) { 1.89 + SECKEY_DestroyPublicKey(publicKey); 1.90 + PORT_FreeArena(arena, false); 1.91 + return NS_ERROR_FAILURE; 1.92 + } 1.93 + 1.94 + // Perform the final verification 1.95 + DER_ConvertBitString(&(sigData.signature)); 1.96 + ss = VFY_VerifyDataWithAlgorithmID((const unsigned char*)nsPromiseFlatCString(aData).get(), 1.97 + aData.Length(), publicKey, 1.98 + &(sigData.signature), 1.99 + &(sigData.signatureAlgorithm), 1.100 + nullptr, nullptr); 1.101 + 1.102 + // Clean up remaining objects 1.103 + SECKEY_DestroyPublicKey(publicKey); 1.104 + PORT_FreeArena(arena, false); 1.105 + 1.106 + *_retval = (ss == SECSuccess); 1.107 + 1.108 + return NS_OK; 1.109 +}