xsec/enc/NSS/NSSCryptoX509.cpp (108 lines of code) (raw):

/** * 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 */