diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /security/nss/cmd/dbtool | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/cmd/dbtool')
-rw-r--r-- | security/nss/cmd/dbtool/Makefile | 50 | ||||
-rw-r--r-- | security/nss/cmd/dbtool/dbtool.c | 830 | ||||
-rw-r--r-- | security/nss/cmd/dbtool/dbtool.gyp | 36 | ||||
-rw-r--r-- | security/nss/cmd/dbtool/manifest.mn | 21 |
4 files changed, 937 insertions, 0 deletions
diff --git a/security/nss/cmd/dbtool/Makefile b/security/nss/cmd/dbtool/Makefile new file mode 100644 index 0000000000..3a5b703130 --- /dev/null +++ b/security/nss/cmd/dbtool/Makefile @@ -0,0 +1,50 @@ +#! gmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../platlibs.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + +#include ../platlibs.mk + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + +include ../platrules.mk + +sdb.c: $(CORE_DEPTH)/lib/softoken/sdb.c + cp $< $@ + + diff --git a/security/nss/cmd/dbtool/dbtool.c b/security/nss/cmd/dbtool/dbtool.c new file mode 100644 index 0000000000..7ae5c36516 --- /dev/null +++ b/security/nss/cmd/dbtool/dbtool.c @@ -0,0 +1,830 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* +** dbtool.c +** +** tool to dump the underlying encoding of a database. This tool duplicates +** some private functions in softoken. It uses libsec and libutil, but no +** other portions of NSS. It currently only works on sqlite databases. For +** an even more primitive dump, use sqlite3 on the individual files. +** +** TODO: dump the meta data for the databases. +** optionally dump more PKCS5 information (KDF/salt/iterations) +** take a password and decode encrypted attributes/verify signed +** attributes. +*/ +#include <stdio.h> +#include <string.h> + +#if defined(WIN32) +#include "fcntl.h" +#include "io.h" +#endif + +/*#include "secutil.h" */ +/*#include "pk11pub.h" */ + +#if defined(XP_UNIX) +#include <unistd.h> +#endif + +#include "nspr.h" +#include "prtypes.h" +#include "nss.h" +#include "secasn1.h" +#include "secder.h" +#include "pk11table.h" +#include "sftkdbt.h" +#include "sdb.h" +#include "secoid.h" + +#include "plgetopt.h" + +static char *progName; + +char *dbDir = NULL; + +static void +Usage() +{ + printf("Usage: %s [-c certprefix] [-k keyprefix] " + "[-V certversion] [-v keyversion]\n" + " [-d dbdir]\n", + progName); + printf("%-20s Directory with cert database (default is .)\n", + "-d certdir"); + printf("%-20s prefix for the cert database (default is \"\")\n", + "-c certprefix"); + printf("%-20s prefix for the key database (default is \"\")\n", + "-k keyprefix"); + printf("%-20s version of the cert database (default is 9)\n", + "-V certversion"); + printf("%-20s version of the key database (default is 4)\n", + "-v keyversion"); + exit(1); +} +#define SFTK_KEYDB_TYPE 0x40000000 +#define SFTK_TOKEN_TYPE 0x80000000 + +/* + * known attributes + */ +static const CK_ATTRIBUTE_TYPE known_attributes[] = { + CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION, + CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER, + CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED, + CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL, + CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY, + CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE, + CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER, + CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE, + CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, + CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, + CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS, + CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE, + CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE, + CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS, + CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE, + CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, + CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS, + CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, + CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE, + CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES, + CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NSS_URL, CKA_NSS_EMAIL, + CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP, + CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES, + CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED, + CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC, + CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION, + CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT, + CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, + CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, + CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM, + CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING, + CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, + CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS, + CKA_PUBLIC_KEY_INFO +}; + +static unsigned int known_attributes_size = sizeof(known_attributes) / + sizeof(known_attributes[0]); + +PRBool +isULONGAttribute(CK_ATTRIBUTE_TYPE type) +{ + switch (type) { + case CKA_CERTIFICATE_CATEGORY: + case CKA_CERTIFICATE_TYPE: + case CKA_CLASS: + case CKA_JAVA_MIDP_SECURITY_DOMAIN: + case CKA_KEY_GEN_MECHANISM: + case CKA_KEY_TYPE: + case CKA_MECHANISM_TYPE: + case CKA_MODULUS_BITS: + case CKA_PRIME_BITS: + case CKA_SUBPRIME_BITS: + case CKA_VALUE_BITS: + case CKA_VALUE_LEN: + + case CKA_TRUST_DIGITAL_SIGNATURE: + case CKA_TRUST_NON_REPUDIATION: + case CKA_TRUST_KEY_ENCIPHERMENT: + case CKA_TRUST_DATA_ENCIPHERMENT: + case CKA_TRUST_KEY_AGREEMENT: + case CKA_TRUST_KEY_CERT_SIGN: + case CKA_TRUST_CRL_SIGN: + + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_CODE_SIGNING: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_IPSEC_END_SYSTEM: + case CKA_TRUST_IPSEC_TUNNEL: + case CKA_TRUST_IPSEC_USER: + case CKA_TRUST_TIME_STAMPING: + case CKA_TRUST_STEP_UP_APPROVED: + return PR_TRUE; + default: + break; + } + return PR_FALSE; +} + +/* are the attributes private? */ +static PRBool +isPrivateAttribute(CK_ATTRIBUTE_TYPE type) +{ + switch (type) { + case CKA_VALUE: + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + return PR_TRUE; + default: + break; + } + return PR_FALSE; +} + +/* These attributes must be authenticated with an hmac. */ +static PRBool +isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type) +{ + switch (type) { + case CKA_MODULUS: + case CKA_PUBLIC_EXPONENT: + case CKA_CERT_SHA1_HASH: + case CKA_CERT_MD5_HASH: + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_CODE_SIGNING: + case CKA_TRUST_STEP_UP_APPROVED: + case CKA_NSS_OVERRIDE_EXTENSIONS: + return PR_TRUE; + default: + break; + } + return PR_FALSE; +} + +/* + * convert a database ulong back to a native ULONG. (reverse of the above + * function. + */ +static CK_ULONG +sdbULong2ULong(unsigned char *data) +{ + int i; + CK_ULONG value = 0; + + for (i = 0; i < SDB_ULONG_SIZE; i++) { + value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE - 1 - i) * PR_BITS_PER_BYTE); + } + return value; +} + +/* PBE defines and functions */ +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) + +typedef struct EncryptedDataInfoStr { + SECAlgorithmID algorithm; + SECItem encryptedData; +} EncryptedDataInfo; + +static const SEC_ASN1Template encryptedDataInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(EncryptedDataInfo) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(EncryptedDataInfo, algorithm), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OCTET_STRING, + offsetof(EncryptedDataInfo, encryptedData) }, + { 0 } +}; + +typedef struct PBEParameterStr { + SECAlgorithmID prfAlg; + SECItem salt; + SECItem iteration; + SECItem keyLength; +} PBEParameter; + +static const SEC_ASN1Template pkcs5V1PBEParameterTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(PBEParameter) }, + { SEC_ASN1_OCTET_STRING, + offsetof(PBEParameter, salt) }, + { SEC_ASN1_INTEGER, + offsetof(PBEParameter, iteration) }, + { 0 } +}; + +static const SEC_ASN1Template pkcs12V2PBEParameterTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) }, + { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) }, + { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) }, + { 0 } +}; + +static const SEC_ASN1Template pkcs5V2PBEParameterTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) }, + /* this is really a choice, but since we don't understand any other + * choice, just inline it. */ + { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) }, + { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) }, + { SEC_ASN1_INTEGER, offsetof(PBEParameter, keyLength) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(PBEParameter, prfAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { 0 } +}; + +typedef struct Pkcs5v2PBEParameterStr { + SECAlgorithmID keyParams; /* parameters of the key generation */ + SECAlgorithmID algParams; /* parameters for the encryption or mac op */ +} Pkcs5v2PBEParameter; + +static const SEC_ASN1Template pkcs5v2PBES2ParameterTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(Pkcs5v2PBEParameter) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(Pkcs5v2PBEParameter, keyParams), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(Pkcs5v2PBEParameter, algParams), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { 0 } +}; + +static inline PRBool +isPKCS12PBE(SECOidTag alg) +{ + switch (alg) { + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + return PR_TRUE; + default: + break; + } + return PR_FALSE; +} + +/* helper functions */ + +/* output an NSS specific attribute or name that wasn't found in our + * pkcs #11 table */ +const char * +makeNSSVendorName(CK_ATTRIBUTE_TYPE attribute, const char *nameType) +{ + static char nss_name[256]; + const char *name = NULL; + if ((attribute >= CKA_NSS) && (attribute < 0xffffffffUL)) { + sprintf(nss_name, "%s+%d", nameType, (int)(attribute - CKA_NSS)); + name = nss_name; + } + return name; +} + +/* turn and attribute into a name */ +const char * +AttributeName(CK_ATTRIBUTE_TYPE attribute) +{ + const char *name = getNameFromAttribute(attribute); + if (!name) { + name = makeNSSVendorName(attribute, "CKA_NSS"); + } + + return name ? name : "UNKNOWN_ATTRIBUTE_TYPE"; +} + +/* turn and error code into a name */ +const char * +ErrorName(CK_RV crv) +{ + const char *error = getName(crv, ConstResult); + if (!error) { + error = makeNSSVendorName(crv, "CKR_NSS"); + } + return error ? error : "UNKNOWN_ERROR"; +} + +/* turn an oud tag into a string */ +const char * +oid2string(SECOidTag alg) +{ + const char *oidstring = SECOID_FindOIDTagDescription(alg); + const char *def = "Invalid oid tag"; /* future build a dotted oid string value here */ + return oidstring ? oidstring : def; +} + +/* dump an arbitary data blob. Dump it has hex with ascii on the side */ +#define ASCCHAR(val) ((val) >= ' ' && (val) <= 0x7e ? (val) : '.') +#define LINE_LENGTH 16 +void +dumpValue(const unsigned char *v, int len) +{ + int i, next = 0; + char string[LINE_LENGTH + 1]; + char space[LINE_LENGTH * 2 + 1]; + char *nl = ""; + char *sp = ""; + PORT_Memset(string, 0, sizeof(string)); + + for (i = 0; i < len; i++) { + if ((i % LINE_LENGTH) == 0) { + printf("%s%s%s ", sp, string, nl); + PORT_Memset(string, 0, sizeof(string)); + next = 0; + nl = "\n"; + sp = " "; + } + printf("%02x", v[i]); + string[next++] = ASCCHAR(v[i]); + } + PORT_Memset(space, 0, sizeof(space)); + i = LINE_LENGTH - (len % LINE_LENGTH); + if (i != LINE_LENGTH) { + int j; + for (j = 0; j < i; j++) { + space[j * 2] = ' '; + space[j * 2 + 1] = ' '; + } + } + printf("%s%s%s%s", space, sp, string, nl); +} + +/* dump a PKCS5/12 PBE blob */ +void +dumpPKCS(unsigned char *val, CK_ULONG len, PRBool *hasSig) +{ + EncryptedDataInfo edi; + SECStatus rv; + SECItem data; + PLArenaPool *arena; + SECOidTag alg, prfAlg; + PBEParameter pbeParam; + unsigned char zero = 0; + const SEC_ASN1Template *template = pkcs5V1PBEParameterTemplate; + int iter, keyLen, i; + + if (hasSig) { + *hasSig = PR_FALSE; + } + + data.data = val; + data.len = len; + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + printf("Couldn't allocate arena\n"); + return; + } + + /* initialize default values */ + PORT_Memset(&pbeParam, 0, sizeof(pbeParam)); + pbeParam.keyLength.data = &zero; + pbeParam.keyLength.len = sizeof(zero); + SECOID_SetAlgorithmID(arena, &pbeParam.prfAlg, SEC_OID_SHA1, NULL); + + /* first crack the encrypted data from the PBE algorithm ID */ + rv = SEC_QuickDERDecodeItem(arena, &edi, encryptedDataInfoTemplate, &data); + if (rv != SECSuccess) { + printf("Encrypted Data, failed to decode\n"); + dumpValue(val, len); + PORT_FreeArena(arena, PR_FALSE); + return; + } + /* now use the pbe secalg to dump info on the pbe */ + alg = SECOID_GetAlgorithmTag(&edi.algorithm); + if ((alg == SEC_OID_PKCS5_PBES2) || (alg == SEC_OID_PKCS5_PBMAC1)) { + Pkcs5v2PBEParameter param; + SECOidTag palg; + const char *typeName = (alg == SEC_OID_PKCS5_PBES2) ? "Encrypted Data PBES2" : "Mac Data PBMAC1"; + + rv = SEC_QuickDERDecodeItem(arena, ¶m, + pkcs5v2PBES2ParameterTemplate, + &edi.algorithm.parameters); + if (rv != SECSuccess) { + printf("%s, failed to decode\n", typeName); + dumpValue(val, len); + PORT_FreeArena(arena, PR_FALSE); + return; + } + palg = SECOID_GetAlgorithmTag(¶m.algParams); + printf("%s alg=%s ", typeName, oid2string(palg)); + if (hasSig && palg == SEC_OID_AES_256_CBC) { + *hasSig = PR_TRUE; + } + template = pkcs5V2PBEParameterTemplate; + edi.algorithm.parameters = param.keyParams.parameters; + } else { + printf("Encrypted Data alg=%s ", oid2string(alg)); + if (alg == SEC_OID_PKCS5_PBKDF2) { + template = pkcs5V2PBEParameterTemplate; + } else if (isPKCS12PBE(alg)) { + template = pkcs12V2PBEParameterTemplate; + } else { + template = pkcs5V1PBEParameterTemplate; + } + } + rv = SEC_QuickDERDecodeItem(arena, &pbeParam, + template, + &edi.algorithm.parameters); + if (rv != SECSuccess) { + printf("( failed to decode params)\n"); + PORT_FreeArena(arena, PR_FALSE); + return; + } + /* dump the pbe parmeters */ + iter = DER_GetInteger(&pbeParam.iteration); + keyLen = DER_GetInteger(&pbeParam.keyLength); + prfAlg = SECOID_GetAlgorithmTag(&pbeParam.prfAlg); + printf("(prf=%s iter=%d keyLen=%d salt=0x", + oid2string(prfAlg), iter, keyLen); + for (i = 0; i < pbeParam.salt.len; i++) + printf("%02x", pbeParam.salt.data[i]); + printf(")\n"); + /* finally dump the raw encrypted data */ + dumpValue(edi.encryptedData.data, edi.encryptedData.len); + PORT_FreeArena(arena, PR_FALSE); +} + +/* dump a long attribute, convert to an unsigned long. PKCS #11 Longs are + * limited to 32 bits by the spec, even if the CK_ULONG is longer */ +void +dumpLongAttribute(CK_ATTRIBUTE_TYPE type, CK_ULONG value) +{ + const char *nameType = "CK_NSS"; + ConstType constType = ConstNone; + const char *valueName = NULL; + + switch (type) { + case CKA_CLASS: + nameType = "CKO_NSS"; + constType = ConstObject; + break; + case CKA_CERTIFICATE_TYPE: + nameType = "CKC_NSS"; + constType = ConstCertType; + break; + case CKA_KEY_TYPE: + nameType = "CKK_NSS"; + constType = ConstKeyType; + break; + case CKA_MECHANISM_TYPE: + nameType = "CKM_NSS"; + constType = ConstMechanism; + break; + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_CODE_SIGNING: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_IPSEC_END_SYSTEM: + case CKA_TRUST_IPSEC_TUNNEL: + case CKA_TRUST_IPSEC_USER: + case CKA_TRUST_TIME_STAMPING: + nameType = "CKT_NSS"; + constType = ConstTrust; + break; + default: + break; + } + /* if value has a symbolic name, use it */ + if (constType != ConstNone) { + valueName = getName(value, constType); + } + if (!valueName) { + valueName = makeNSSVendorName(value, nameType); + } + if (!valueName) { + printf("%d (0x%08x)\n", (int)value, (int)value); + } else { + printf("%s (0x%08x)\n", valueName, (int)value); + } +} + +/* dump a signature for an object */ +static const char META_SIG_TEMPLATE[] = "sig_%s_%08x_%08x"; +void +dumpSignature(CK_ATTRIBUTE_TYPE attribute, SDB *keydb, PRBool isKey, + CK_OBJECT_HANDLE objectID, PRBool force) +{ + char id[30]; + CK_RV crv; + SECItem signText; + unsigned char signData[SDB_MAX_META_DATA_LEN]; + + if (!force && !isAuthenticatedAttribute(attribute)) { + return; + } + sprintf(id, META_SIG_TEMPLATE, + isKey ? "key" : "cert", + (unsigned int)objectID, (unsigned int)attribute); + printf(" Signature %s:", id); + signText.data = signData; + signText.len = sizeof(signData); + + crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL); + if ((crv != CKR_OK) && isKey) { + sprintf(id, META_SIG_TEMPLATE, + isKey ? "key" : "cert", (unsigned int)(objectID | SFTK_KEYDB_TYPE | SFTK_TOKEN_TYPE), + (unsigned int)attribute); + crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL); + } + if (crv != CKR_OK) { + printf(" FAILED %s with %s (0x%08x)\n", id, ErrorName(crv), (int)crv); + return; + } + dumpPKCS(signText.data, signText.len, NULL); + return; +} + +/* dump an attribute. use the helper functions above */ +void +dumpAttribute(CK_ATTRIBUTE *template, SDB *keydb, PRBool isKey, + CK_OBJECT_HANDLE id) +{ + CK_ATTRIBUTE_TYPE attribute = template->type; + printf(" %s(0x%08x): ", AttributeName(attribute), (int)attribute); + if (template->pValue == NULL) { + printf("NULL (%d)\n", (int)template->ulValueLen); + return; + } + if (template->ulValueLen == SDB_ULONG_SIZE && isULONGAttribute(attribute)) { + CK_ULONG value = sdbULong2ULong(template->pValue); + dumpLongAttribute(attribute, value); + return; + } + if (template->ulValueLen == 1) { + unsigned char val = *(unsigned char *)template->pValue; + switch (val) { + case 0: + printf("CK_FALSE\n"); + break; + case 1: + printf("CK_TRUE\n"); + break; + default: + printf("%d 0x%02x %c\n", val, val, ASCCHAR(val)); + break; + } + return; + } + if (isKey && isPrivateAttribute(attribute)) { + PRBool hasSig = PR_FALSE; + dumpPKCS(template->pValue, template->ulValueLen, &hasSig); + if (hasSig) { + dumpSignature(attribute, keydb, isKey, id, PR_TRUE); + } + return; + } + if (template->ulValueLen == 0) { + printf("empty"); + } + printf("\n"); + dumpValue(template->pValue, template->ulValueLen); +} + +/* dump all the attributes in an object */ +void +dumpObject(CK_OBJECT_HANDLE id, SDB *db, SDB *keydb, PRBool isKey) +{ + CK_RV crv; + int i; + CK_ATTRIBUTE template; + char buffer[2048]; + char *alloc = NULL; + + printf(" Object 0x%08x:\n", (int)id); + for (i = 0; i < known_attributes_size; i++) { + CK_ATTRIBUTE_TYPE attribute = known_attributes[i]; + template.type = attribute; + template.pValue = NULL; + template.ulValueLen = 0; + crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1); + + if (crv != CKR_OK) { + if (crv != CKR_ATTRIBUTE_TYPE_INVALID) { + PR_fprintf(PR_STDERR, " " + "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n", + AttributeName(attribute), (int)attribute, + ErrorName(crv), (int)crv); + } + continue; + } + + if (template.ulValueLen < sizeof(buffer)) { + template.pValue = buffer; + } else { + alloc = PORT_Alloc(template.ulValueLen); + template.pValue = alloc; + } + if (template.pValue == NULL) { + PR_fprintf(PR_STDERR, " " + "Could allocate %d bytes for Attribute %s (0x%08x)\n", + (int)template.ulValueLen, + AttributeName(attribute), (int)attribute); + continue; + } + crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1); + + if (crv != CKR_OK) { + if (crv != CKR_ATTRIBUTE_TYPE_INVALID) { + PR_fprintf(PR_STDERR, " " + "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n", + AttributeName(attribute), (int)attribute, + ErrorName(crv), (int)crv); + } + if (alloc) { + PORT_Free(alloc); + alloc = NULL; + } + continue; + } + + dumpAttribute(&template, keydb, isKey, id); + dumpSignature(template.type, keydb, isKey, id, PR_FALSE); + if (alloc) { + PORT_Free(alloc); + alloc = NULL; + } + } +} + +/* dump all the objects in a database */ +void +dumpDB(SDB *db, const char *name, SDB *keydb, PRBool isKey) +{ + SDBFind *findHandle = NULL; + CK_BBOOL isTrue = 1; + CK_ATTRIBUTE allObjectTemplate = { CKA_TOKEN, NULL, 1 }; + CK_ULONG allObjectTemplateCount = 1; + PRBool recordFound = PR_FALSE; + CK_RV crv = CKR_OK; + CK_ULONG objectCount = 0; + printf("%s:\n", name); + + allObjectTemplate.pValue = &isTrue; + crv = (*db->sdb_FindObjectsInit)(db, &allObjectTemplate, + allObjectTemplateCount, &findHandle); + do { + CK_OBJECT_HANDLE id; + recordFound = PR_FALSE; + crv = (*db->sdb_FindObjects)(db, findHandle, &id, 1, &objectCount); + if ((crv == CKR_OK) && (objectCount == 1)) { + recordFound = PR_TRUE; + dumpObject(id, db, keydb, isKey); + } + } while (recordFound); + if (crv != CKR_OK) { + PR_fprintf(PR_STDERR, + "Last record return PKCS #11 error = %s (0x%08x)\n", + ErrorName(crv), (int)crv); + } + (*db->sdb_FindObjectsFinal)(db, findHandle); +} + +static char * +secu_ConfigDirectory(const char *base) +{ + static PRBool initted = PR_FALSE; + const char *dir = ".netscape"; + char *home; + static char buf[1000]; + + if (initted) + return buf; + + if (base == NULL || *base == 0) { + home = PR_GetEnvSecure("HOME"); + if (!home) + home = ""; + + if (*home && home[strlen(home) - 1] == '/') + sprintf(buf, "%.900s%s", home, dir); + else + sprintf(buf, "%.900s/%s", home, dir); + } else { + sprintf(buf, "%.900s", base); + if (buf[strlen(buf) - 1] == '/') + buf[strlen(buf) - 1] = 0; + } + + initted = PR_TRUE; + return buf; +} + +int +main(int argc, char **argv) +{ + PLOptState *optstate; + PLOptStatus optstatus; + char *certPrefix = "", *keyPrefix = ""; + int cert_version = 9; + int key_version = 4; + SDB *certdb = NULL; + SDB *keydb = NULL; + PRBool isNew = PR_FALSE; + + CK_RV crv; + + progName = strrchr(argv[0], '/'); + if (!progName) + progName = strrchr(argv[0], '\\'); + progName = progName ? progName + 1 : argv[0]; + + optstate = PL_CreateOptState(argc, argv, "d:c:k:v:V:h"); + + while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { + switch (optstate->option) { + case 'h': + default: + Usage(); + break; + + case 'd': + dbDir = PORT_Strdup(optstate->value); + break; + + case 'c': + certPrefix = PORT_Strdup(optstate->value); + break; + + case 'k': + keyPrefix = PORT_Strdup(optstate->value); + break; + + case 'v': + key_version = atoi(optstate->value); + break; + + case 'V': + cert_version = atoi(optstate->value); + break; + } + } + PL_DestroyOptState(optstate); + if (optstatus == PL_OPT_BAD) + Usage(); + + if (dbDir) { + char *tmp = dbDir; + dbDir = secu_ConfigDirectory(tmp); + PORT_Free(tmp); + } else { + dbDir = secu_ConfigDirectory(NULL); + } + PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir); + + if (dbDir[0] == '\0') { + PR_fprintf(PR_STDERR, + "ERROR: Directory \"%s\" does not exist.\n", dbDir); + return 1; + } + + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + SECOID_Init(); + + crv = s_open(dbDir, certPrefix, keyPrefix, cert_version, key_version, + SDB_RDONLY, &certdb, &keydb, &isNew); + if (crv != CKR_OK) { + PR_fprintf(PR_STDERR, + "Couldn't open databased in %s, error=%s (0x%08x)\n", + dbDir, ErrorName(crv), (int)crv); + return 1; + } + + /* now dump the objects in the cert database */ + dumpDB(certdb, "CertDB", keydb, PR_FALSE); + dumpDB(keydb, "KeyDB", keydb, PR_TRUE); + return 0; +} diff --git a/security/nss/cmd/dbtool/dbtool.gyp b/security/nss/cmd/dbtool/dbtool.gyp new file mode 100644 index 0000000000..4c1081f810 --- /dev/null +++ b/security/nss/cmd/dbtool/dbtool.gyp @@ -0,0 +1,36 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../../cmd/platlibs.gypi' + ], + 'targets': [ + { + 'target_name': 'dbtool', + 'type': 'executable', + 'sources': [ + 'dbtool.c', + '../../lib/softoken/sdb.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:dbm_exports', + '<(DEPTH)/exports.gyp:nss_exports' + ], + 'conditions': [ + [ 'use_system_sqlite==1', { + 'dependencies': [ + '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3', + ], + }, { + 'dependencies': [ + '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite', + ], + }], + ] } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/cmd/dbtool/manifest.mn b/security/nss/cmd/dbtool/manifest.mn new file mode 100644 index 0000000000..fa93eaacb9 --- /dev/null +++ b/security/nss/cmd/dbtool/manifest.mn @@ -0,0 +1,21 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +CORE_DEPTH = ../.. + +# MODULE public and private header directories are implicitly REQUIRED. +MODULE = nss + +USE_STATIC_LIBS = 1 + +# DIRS = + +CSRCS = dbtool.c sdb.c + +# sdb.c is copied for softoken, clean it up on make clean +GARBAGE = sdb.c + +PROGRAM = dbtool + |