CERTCertificate* find_certificate(CERTCertDBHandle *handle, const char *name, PRBool ascii) { CERTCertificate *cert = NULL; SECItem der; PRFileDesc *certFile; if (handle == NULL || name == NULL) return NULL; if (ascii == PR_FALSE) { /* by default need to check if there is cert nick is given */ cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) name); if (cert != NULL) return cert; } certFile = PR_Open(name, PR_RDONLY, 0); if (certFile == NULL) { return NULL; } if (SECU_ReadDERFromFile(&der, certFile, ascii, PR_FALSE) == SECSuccess) { cert = CERT_DecodeCertFromPackage((char*)der.data, der.len); SECITEM_FreeItem(&der, PR_FALSE); } PR_Close(certFile); return cert; }
static int __pkcs11h_crypto_nss_certificate_is_issuer ( IN void * const global_data, IN const unsigned char * const issuer_blob, IN const size_t issuer_blob_size, IN const unsigned char * const cert_blob, IN const size_t cert_blob_size ) { PKCS11H_BOOL is_issuer = FALSE; CERTCertificate *cert = NULL; CERTCertificate *issuer = NULL; (void)global_data; /*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/ _PKCS11H_ASSERT (issuer_blob!=NULL); _PKCS11H_ASSERT (cert_blob!=NULL); if ((issuer = CERT_DecodeCertFromPackage ((char *)issuer_blob, issuer_blob_size)) == NULL) { goto cleanup; } if ((cert = CERT_DecodeCertFromPackage ((char *)cert_blob, cert_blob_size)) == NULL) { goto cleanup; } is_issuer = CERT_VerifySignedDataWithPublicKeyInfo ( &cert->signatureWrap, &issuer->subjectPublicKeyInfo, NULL ) == SECSuccess; cleanup: if (cert != NULL) { CERT_DestroyCertificate (cert); } if (issuer != NULL) { CERT_DestroyCertificate (issuer); } return is_issuer; }
int main(int argc, char **argv) { if (NSS_NoDB_Init(NULL) != SECSuccess) { printf(" >>> NSS_NoDB_Init() failed.\n"); return 1; } if (argc < 3) { printf(" >>> I need a DER encoded file to read and have to know what to do with it [decode, private]!\n"); return 1; } PRFileDesc* file = PR_Open(argv[1], PR_RDONLY, 0); SECItem data = {0, NULL, 0}; if (SECU_ReadDERFromFile(&data, file, PR_FALSE, PR_FALSE) != SECSuccess) { printf(" >>> SECU_ReadDERFromFile() failed.\n"); return 1; } PR_Close(file); if (strcmp(argv[2], "decode") == 0) { CERTCertificate *cert = CERT_DecodeCertFromPackage((char*)data.data, data.len); if (cert){ printf(" >>> read cert!\n"); printf(" >>> SN: %s\n", cert->subjectName); printf(" >>> IN: %s\n", cert->issuerName); CERT_DestroyCertificate(cert); } else { printf(" >>> CERT_DecodeCertFromPackage failed.\n"); SECITEM_FreeItem(&data, PR_FALSE); return 1; } } if (argv[2] == "private") { PK11SlotInfo* slot = PK11_GetInternalSlot(); if (!slot) { printf(" >>> PK11_GetInternalSlot() failed.\n"); SECITEM_FreeItem(&data, PR_FALSE); return 1; } SECKEYPrivateKey* privKey; if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &data, NULL, NULL, PR_FALSE, PR_FALSE, KU_ALL, &privKey, NULL) != SECSuccess) { printf(" >>> PK11_ImportDERPrivateKeyInfoAndReturnKey() failed.\n"); SECITEM_FreeItem(&data, PR_FALSE); return 1; } } printf(" !!! Done.\n"); return 0; }
static int __pkcs11h_crypto_nss_certificate_get_expiration ( IN void * const global_data, IN const unsigned char * const blob, IN const size_t blob_size, OUT time_t * const expiration ) { CERTCertificate *cert = NULL; PRTime pr_notBefore, pr_notAfter; time_t notBefore, notAfter; time_t now = time (NULL); (void)global_data; *expiration = (time_t)0; /*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/ _PKCS11H_ASSERT (blob!=NULL); _PKCS11H_ASSERT (expiration!=NULL); if ((cert = CERT_DecodeCertFromPackage ((char *)blob, blob_size)) == NULL) { goto cleanup; } if (CERT_GetCertTimes (cert, &pr_notBefore, &pr_notAfter) != SECSuccess) { goto cleanup; } notBefore = pr_notBefore/1000000; notAfter = pr_notAfter/1000000; notBefore = mktime (gmtime (¬Before)); notBefore += (int)(mktime (localtime (¬Before)) - mktime (gmtime (¬Before))); notAfter = mktime (gmtime (¬After)); notAfter += (int)(mktime (localtime (¬After)) - mktime (gmtime (¬After))); if ( now >= notBefore && now <= notAfter ) { *expiration = notAfter; } cleanup: if (cert != NULL) { CERT_DestroyCertificate (cert); } return *expiration != (time_t)0; }
static int __pkcs11h_crypto_nss_certificate_get_dn ( IN void * const global_data, IN const unsigned char * const blob, IN const size_t blob_size, OUT char * const dn, IN const size_t dn_max ) { CERTCertificate *cert = NULL; (void)global_data; /*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/ _PKCS11H_ASSERT (blob!=NULL); _PKCS11H_ASSERT (dn!=NULL); _PKCS11H_ASSERT (dn_max>0); dn[0] = '\x0'; if ((cert = CERT_DecodeCertFromPackage ((char *)blob, blob_size)) == NULL) { goto cleanup; } if (strlen (cert->subjectName) >= dn_max) { goto cleanup; } strcpy (dn, cert->subjectName); cleanup: if (cert != NULL) { CERT_DestroyCertificate (cert); } return dn[0] != '\x0'; }
bool nsNSSCertificate::InitFromDER(char *certDER, int derLen) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) return false; if (!certDER || !derLen) return false; CERTCertificate *aCert = CERT_DecodeCertFromPackage(certDER, derLen); if (!aCert) return false; if(aCert->dbhandle == nullptr) { aCert->dbhandle = CERT_GetDefaultCertDB(); } mCert = aCert; return true; }
char * crypto_encrypt (const char *cipher, const guint8 *data, gsize data_len, const char *iv, gsize iv_len, const char *key, gsize key_len, gsize *out_len, GError **error) { SECStatus ret; CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; PK11SlotInfo *slot = NULL; SECItem key_item = { .data = (unsigned char *) key, .len = key_len }; SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len }; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; unsigned char *output, *padded_buf; gsize output_len; int encrypted_len = 0, i; gboolean success = FALSE; gsize padded_buf_len, pad_len; if (!crypto_init (error)) return NULL; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) cipher_mech = CKM_DES3_CBC_PAD; else if (!strcmp (cipher, CIPHER_AES_CBC)) cipher_mech = CKM_AES_CBC_PAD; else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } /* If data->len % ivlen == 0, then we add another complete block * onto the end so that the decrypter knows there's padding. */ pad_len = iv_len - (data_len % iv_len); output_len = padded_buf_len = data_len + pad_len; padded_buf = g_malloc0 (padded_buf_len); memcpy (padded_buf, data, data_len); for (i = 0; i < pad_len; i++) padded_buf[data_len + i] = (guint8) (pad_len & 0xFF); output = g_malloc0 (output_len); slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the encryption cipher slot.")); goto out; } sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (!sym_key) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set symmetric key for encryption.")); goto out; } sec_param = PK11_ParamFromIV (cipher_mech, &iv_item); if (!sec_param) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set IV for encryption.")); goto out; } ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param); if (!ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to initialize the encryption context.")); goto out; } ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len); if (ret != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to encrypt: %d."), PORT_GetError ()); goto out; } if (encrypted_len != output_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Unexpected amount of data after encrypting.")); goto out; } *out_len = encrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); if (sym_key) PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); if (slot) PK11_FreeSlot (slot); memset (padded_buf, 0, padded_buf_len); g_free (padded_buf); if (!success) { memset (output, 0, output_len); g_free (output); output = NULL; } return (char *) output; } NMCryptoFileFormat crypto_verify_cert (const unsigned char *data, gsize len, GError **error) { CERTCertificate *cert; if (!crypto_init (error)) return NM_CRYPTO_FILE_FORMAT_UNKNOWN; /* Try DER/PEM first */ cert = CERT_DecodeCertFromPackage ((char *) data, len); if (!cert) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %d"), PORT_GetError()); return NM_CRYPTO_FILE_FORMAT_UNKNOWN; } CERT_DestroyCertificate (cert); return NM_CRYPTO_FILE_FORMAT_X509; } gboolean crypto_verify_pkcs12 (const guint8 *data, gsize data_len, const char *password, GError **error) { SEC_PKCS12DecoderContext *p12ctx = NULL; SECItem pw = { 0 }; PK11SlotInfo *slot = NULL; SECStatus s; gunichar2 *ucs2_password; glong ucs2_chars = 0; #ifndef WORDS_BIGENDIAN guint16 *p; #endif /* WORDS_BIGENDIAN */ if (error) g_return_val_if_fail (*error == NULL, FALSE); if (!crypto_init (error)) return FALSE; /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do * any conversions for us. */ if (password && *password) { if (!g_utf8_validate (password, -1, NULL)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_PASSWORD, _("Password must be UTF-8")); return FALSE; } ucs2_password = g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); /* Can't fail if g_utf8_validate() succeeded */ g_return_val_if_fail (ucs2_password != NULL && ucs2_chars != 0, FALSE); ucs2_chars *= 2; /* convert # UCS2 characters -> bytes */ pw.data = PORT_ZAlloc(ucs2_chars + 2); memcpy (pw.data, ucs2_password, ucs2_chars); pw.len = ucs2_chars + 2; /* include terminating NULL */ memset (ucs2_password, 0, ucs2_chars); g_free (ucs2_password); #ifndef WORDS_BIGENDIAN for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++) *p = GUINT16_SWAP_LE_BE (*p); #endif /* WORDS_BIGENDIAN */ } else { /* NULL password */ pw.data = NULL; pw.len = 0; } slot = PK11_GetInternalKeySlot(); p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (!p12ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#12 decoder: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderVerify (p12ctx); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %d"), PORT_GetError()); goto error; } SEC_PKCS12DecoderFinish (p12ctx); SECITEM_ZfreeItem (&pw, PR_FALSE); return TRUE; error: if (p12ctx) SEC_PKCS12DecoderFinish (p12ctx); if (slot) PK11_FreeSlot(slot); SECITEM_ZfreeItem (&pw, PR_FALSE); return FALSE; }
// nsCMSSecureMessage::SendMessage nsresult nsCMSSecureMessage:: SendMessage(const char *msg, const char *base64Cert, char ** _retval) { nsNSSShutDownPreventionLock locker; PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage\n")); nsresult rv = NS_OK; CERTCertificate *cert = 0; NSSCMSMessage *cmsMsg = 0; unsigned char *certDER = 0; PRInt32 derLen; NSSCMSEnvelopedData *env; NSSCMSContentInfo *cinfo; NSSCMSRecipientInfo *rcpt; SECItem item; SECItem output; PLArenaPool *arena = PORT_NewArena(1024); SECStatus s; nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext(); /* Step 0. Create a CMS Message */ cmsMsg = NSS_CMSMessage_Create(NULL); if (!cmsMsg) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't create NSSCMSMessage\n")); rv = NS_ERROR_FAILURE; goto done; } /* Step 1. Import the certificate into NSS */ rv = decode(base64Cert, &certDER, &derLen); if (NS_FAILED(rv)) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't decode / import cert into NSS\n")); goto done; } cert = CERT_DecodeCertFromPackage((char *)certDER, derLen); if (!cert) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't decode cert from package\n")); rv = NS_ERROR_FAILURE; goto done; } #if 0 cert->dbhandle = CERT_GetDefaultCertDB(); /* work-around */ #endif /* Step 2. Get a signature cert */ /* Step 3. Build inner (signature) content */ /* Step 4. Build outer (enveloped) content */ env = NSS_CMSEnvelopedData_Create(cmsMsg, SEC_OID_DES_EDE3_CBC, 0); if (!env) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't create envelope data\n")); rv = NS_ERROR_FAILURE; goto done; } cinfo = NSS_CMSEnvelopedData_GetContentInfo(env); item.data = (unsigned char *)msg; item.len = strlen(msg); /* XPCOM equiv?? */ s = NSS_CMSContentInfo_SetContent_Data(cmsMsg, cinfo, 0, PR_FALSE); if (s != SECSuccess) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't set content data\n")); rv = NS_ERROR_FAILURE; goto done; } rcpt = NSS_CMSRecipientInfo_Create(cmsMsg, cert); if (!rcpt) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't create recipient info\n")); rv = NS_ERROR_FAILURE; goto done; } s = NSS_CMSEnvelopedData_AddRecipient(env, rcpt); if (s != SECSuccess) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't add recipient\n")); rv = NS_ERROR_FAILURE; goto done; } /* Step 5. Add content to message */ cinfo = NSS_CMSMessage_GetContentInfo(cmsMsg); s = NSS_CMSContentInfo_SetContent_EnvelopedData(cmsMsg, cinfo, env); if (s != SECSuccess) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't set content enveloped data\n")); rv = NS_ERROR_FAILURE; goto done; } /* Step 6. Encode */ NSSCMSEncoderContext *ecx; output.data = 0; output.len = 0; ecx = NSS_CMSEncoder_Start(cmsMsg, 0, 0, &output, arena, 0, ctx, 0, 0, 0, 0); if (!ecx) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't start cms encoder\n")); rv = NS_ERROR_FAILURE; goto done; } s = NSS_CMSEncoder_Update(ecx, msg, strlen(msg)); if (s != SECSuccess) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't update encoder\n")); rv = NS_ERROR_FAILURE; goto done; } s = NSS_CMSEncoder_Finish(ecx); if (s != SECSuccess) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't finish encoder\n")); rv = NS_ERROR_FAILURE; goto done; } /* Step 7. Base64 encode and return the result */ rv = encode(output.data, output.len, _retval); done: if (certDER) nsCRT::free((char *)certDER); if (cert) CERT_DestroyCertificate(cert); if (cmsMsg) NSS_CMSMessage_Destroy(cmsMsg); if (arena) PORT_FreeArena(arena, PR_FALSE); /* PR_FALSE? */ return rv; }