blob: 3521c27291333df4e42eb1719c1aeb27d060ea85 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* XSEC
*
* NSSCryptoX509:= NSS based class for handling X509 (V3) certificates
*
* Author(s): Milan Tomic
*
*/
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/enc/NSS/NSSCryptoProvider.hpp>
#include <xsec/enc/NSS/NSSCryptoX509.hpp>
#include <xsec/enc/NSS/NSSCryptoKeyDSA.hpp>
#include <xsec/enc/NSS/NSSCryptoKeyRSA.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>
#if defined (XSEC_HAVE_NSS)
extern "C" {
extern CERTCertificate *
__CERT_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname);
}
#include <xercesc/util/Janitor.hpp>
XSEC_USING_XERCES(ArrayJanitor);
// --------------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------------
NSSCryptoX509::NSSCryptoX509() : m_DERX509(""), mp_cert(NULL) {
}
// --------------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------------
NSSCryptoX509::NSSCryptoX509(CERTCertificate * pCert) {
// Build this from an existing CERTCertificate structure
mp_cert = pCert;
unsigned char * encCert;
unsigned long len = mp_cert->derCert.len * 2;
XSECnew(encCert, unsigned char [len]);
ArrayJanitor<unsigned char> j_encCert(encCert);
// Base64 Encode
XSCryptCryptoBase64 b64;
b64.encodeInit();
unsigned long encCertLen = b64.encode(mp_cert->derCert.data, mp_cert->derCert.len, encCert, len);
encCertLen += b64.encodeFinish(&encCert[encCertLen], len - encCertLen);
// Check the result
if (encCert == NULL) {
throw XSECCryptoException(XSECCryptoException::X509Error,
"NSSX509:NSSX509 - Error encoding certificate");
}
m_DERX509.sbMemcpyIn(encCert, encCertLen);
m_DERX509[encCertLen] = '\0';
}
// --------------------------------------------------------------------------------
// Destructor
// --------------------------------------------------------------------------------
NSSCryptoX509::~NSSCryptoX509() {
if (mp_cert != 0)
CERT_DestroyCertificate(mp_cert);
}
// --------------------------------------------------------------------------------
// Load X509
// --------------------------------------------------------------------------------
void NSSCryptoX509::loadX509Base64Bin(const char * buf, unsigned int len) {
unsigned char * rawCert;
XSECnew(rawCert, unsigned char [len]);
ArrayJanitor<unsigned char> j_rawCert(rawCert);
// Base64 Decode
XSCryptCryptoBase64 b64;
b64.decodeInit();
unsigned int rawCertLen = b64.decode((unsigned char *) buf, len, rawCert, len);
rawCertLen += b64.decodeFinish(&rawCert[rawCertLen], len - rawCertLen);
// Now load certificate
SECItem i;
i.type = siBuffer;
i.data = rawCert;
i.len = rawCertLen;
SECItem *certs[1];
certs[0] = &i;
// For returning
CERTCertificate **certArray = NULL;
/* mp_cert = __CERT_DecodeDERCertificate(&i, PR_TRUE, NULL); */
CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageUserCertImport, 1, certs,
&certArray, PR_FALSE, PR_FALSE, NULL);
// 1. If you got an compiler error here add into "nss/cert.h" delacarion for
// CERT_DecodeDERCertificate() (the same parameters as for __CERT_DecodeDERCertificate())
// 2. Since __CERT_DecodeDERCertificate is a private function we might consider using
// __CERT_NewTempCertificate() or CERT_ImportCerts() instead.
// Now map to our cert
if (certArray == NULL) {
throw XSECCryptoException(XSECCryptoException::X509Error,
"NSSX509:loadX509Base64Bin - Error decoding certificate");
}
mp_cert = certArray[0];
if (mp_cert == 0) {
throw XSECCryptoException(XSECCryptoException::X509Error,
"NSSX509:loadX509Base64Bin - Error decoding certificate");
}
m_DERX509.sbMemcpyIn(buf, len);
m_DERX509[len] = '\0';
}
// --------------------------------------------------------------------------------
// Get NSS provider name
// --------------------------------------------------------------------------------
const XMLCh * NSSCryptoX509::getProviderName() const {
return DSIGConstants::s_unicodeStrPROVNSS;
}
// --------------------------------------------------------------------------------
// Get publickey type: RSA or DSA
// --------------------------------------------------------------------------------
XSECCryptoKey::KeyType NSSCryptoX509::getPublicKeyType() const {
if (mp_cert == NULL) {
throw XSECCryptoException(XSECCryptoException::X509Error,
"NSS:X509 - getPublicKeyType called before X509 loaded");
}
XSECCryptoKey::KeyType kt = XSECCryptoKey::KEY_NONE;
SECKEYPublicKey * pubkey = CERT_ExtractPublicKey(mp_cert);
if (pubkey == 0) {
throw XSECCryptoException(XSECCryptoException::X509Error,
"NSS:X509 - Error extracting public key from X509 certificate");
}
if (pubkey->keyType == dsaKey)
kt = XSECCryptoKey::KEY_DSA_PUBLIC;
if (pubkey->keyType == rsaKey)
kt = XSECCryptoKey::KEY_RSA_PUBLIC;
SECKEY_DestroyPublicKey(pubkey);
return kt;
}
// --------------------------------------------------------------------------------
// Replicate public key
// --------------------------------------------------------------------------------
XSECCryptoKey * NSSCryptoX509::clonePublicKey() const {
if (mp_cert == NULL) {
throw XSECCryptoException(XSECCryptoException::X509Error,
"NSS:X509 - clonePublicKey called before X509 loaded");
}
// Import the key into the provider to get a pointer to the key
if (getPublicKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC) {
SECKEYPublicKey * pubkey = CERT_ExtractPublicKey(mp_cert);
// Now that we have a handle for the DSA key, create a DSA Key object to
// wrap it in
NSSCryptoKeyDSA * ret;
XSECnew(ret, NSSCryptoKeyDSA(pubkey));
return ret;
}
if (getPublicKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC) {
SECKEYPublicKey * pubkey = CERT_ExtractPublicKey(mp_cert);
// Now that we have a handle for the DSA key, create a DSA Key object to
// wrap it in
NSSCryptoKeyRSA * ret;
XSECnew(ret, NSSCryptoKeyRSA(pubkey));
return ret;
}
return NULL; // Unknown key type, but not necessarily an error
}
#endif /* XSEC_HAVE_NSS */