validation.c (11695B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifdef _CRTDBG_MAP_ALLOC 6 #include <stdlib.h> 7 #include <crtdbg.h> 8 #endif 9 10 #include "nspr.h" 11 #include "secutil.h" 12 #include "pk11func.h" 13 #include "nss.h" 14 #include "secport.h" 15 #include "secpkcs5.h" 16 #include "sechash.h" 17 #include "certdb.h" 18 #include "secmod.h" 19 20 static char *progName; 21 PRBool debug = PR_FALSE; 22 23 #define ERR_USAGE 2 24 #define ERR_PK11GETSLOT 13 25 26 static void 27 Usage() 28 { 29 #define FPS PR_fprintf(PR_STDERR, 30 FPS "Usage: %s [-d certdir] [-P dbprefix] [-h tokenname]\n", 31 progName); 32 FPS "\t\t [-k slotpwfile | -K slotpw] [-v][-o|-p]\n"); 33 34 exit(ERR_USAGE); 35 } 36 37 typedef enum { 38 tagULong, 39 tagULongFlag, 40 tagVersion, 41 tagUtf8, 42 tagValidationAuthorityType, 43 tagValidationType, 44 } tagType; 45 46 typedef struct { 47 const char *attributeName; 48 tagType attributeStorageType; 49 } attributeTag; 50 51 enum { 52 opt_CertDir = 0, 53 opt_TokenName, 54 opt_SlotPWFile, 55 opt_SlotPW, 56 opt_DBPrefix, 57 opt_Debug, 58 /* we determine which validation objects we search for by 59 * whether or not pkcs 11 v3.2 is available, These options 60 * override the default */ 61 opt_ForceVendor, 62 opt_ForcePKCS11, 63 }; 64 65 static secuCommandFlag validation_options[] = { 66 { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, 67 { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, 68 { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE }, 69 { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE }, 70 { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, 71 { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE }, 72 { /* opt_ForceVendor */ 'o', PR_FALSE, 0, PR_FALSE }, 73 { /* opt_ForcePKCS11 */ 'p', PR_FALSE, 0, PR_FALSE } 74 }; 75 76 const char *validationAuthorityTable[] = { 77 "Unspecified", 78 "NIST/CMVP", 79 "Common Criteria" 80 }; 81 const size_t validationAuthorityTableSize = PR_ARRAY_SIZE(validationAuthorityTable); 82 83 const char *validationTypeTable[] = { 84 "Unspecified", 85 "Software", 86 "Hardware", 87 "Firmware", 88 "Hybrid", 89 }; 90 const size_t validationTypeTableSize = PR_ARRAY_SIZE(validationTypeTable); 91 92 void 93 printULongTag(tagType tag, CK_ULONG value) 94 { 95 switch (tag) { 96 case tagULongFlag: 97 for (int i = 31; i >= 0; i--) { 98 printf("%u", (unsigned int)(value >> i) & 0x1); 99 } 100 printf("\n"); 101 return; /* done */ 102 case tagValidationAuthorityType: 103 if (value < validationAuthorityTableSize) { 104 printf("%s\n", validationAuthorityTable[value]); 105 return; 106 } 107 break; /* fall through to default */ 108 case tagValidationType: 109 if (value < validationTypeTableSize) { 110 printf("%s\n", validationTypeTable[value]); 111 return; 112 } 113 break; /* fall through to default */ 114 default: 115 break; 116 } 117 printf("%ld\n", value); 118 } 119 120 void 121 dump_Raw(char *label, CK_ATTRIBUTE *attr) 122 { 123 int i; 124 unsigned char *value = (unsigned char *)attr->pValue; 125 printf("0x"); 126 for (i = 0; i < attr->ulValueLen; i++) { 127 printf("%02x", value[i]); 128 } 129 printf("<%s>\n", label); 130 } 131 132 SECStatus 133 dump_validations(CK_OBJECT_CLASS objc, CK_ATTRIBUTE *template, int count, 134 attributeTag *tags, PK11SlotInfo *slot) 135 { 136 PK11GenericObject *objs, *obj; 137 138 objs = PK11_FindGenericObjects(slot, objc); 139 140 for (obj = objs; obj != NULL; obj = PK11_GetNextGenericObject(obj)) { 141 int i; 142 printf("Validation Object:\n"); 143 PK11_ReadRawAttributes(NULL, PK11_TypeGeneric, obj, template, count); 144 for (i = 0; i < count; i++) { 145 CK_ULONG ulong; 146 CK_VERSION version; 147 int len = template[i].ulValueLen; 148 printf(" %s: ", tags[i].attributeName); 149 if (len < 0) { 150 printf("<failed>\n"); 151 } else if (len == 0) { 152 printf("<empty>\n"); 153 } else 154 switch (tags[i].attributeStorageType) { 155 case tagULongFlag: 156 case tagValidationAuthorityType: 157 case tagValidationType: 158 case tagULong: 159 if (len != sizeof(CK_ULONG)) { 160 dump_Raw("bad ulong", &template[i]); 161 break; 162 } 163 ulong = *(CK_ULONG *)template[i].pValue; 164 printULongTag(tags[i].attributeStorageType, ulong); 165 break; 166 case tagVersion: 167 if (len != sizeof(CK_VERSION)) { 168 dump_Raw("bad version", &template[i]); 169 break; 170 } 171 version = *(CK_VERSION *)template[i].pValue; 172 printf("%d.%d\n", version.major, version.minor); 173 break; 174 case tagUtf8: 175 printf("%.*s\n", len, (char *)template[i].pValue); 176 break; 177 default: 178 dump_Raw("unknown tag", &template[i]); 179 break; 180 } 181 PORT_Free(template[i].pValue); 182 template[i].pValue = NULL; 183 template[i].ulValueLen = 0; 184 } 185 } 186 PK11_DestroyGenericObjects(objs); 187 return SECSuccess; 188 } 189 190 int 191 main(int argc, char **argv) 192 { 193 secuPWData slotPw = { PW_NONE, NULL }; 194 secuPWData p12FilePw = { PW_NONE, NULL }; 195 PK11SlotInfo *slot = NULL; 196 char *slotname = NULL; 197 char *dbprefix = ""; 198 char *nssdir = NULL; 199 SECStatus rv = SECFailure; 200 secuCommand validation; 201 int local_errno = 0; 202 203 CK_ATTRIBUTE validation_template[] = { 204 { CKA_VALIDATION_MODULE_ID, NULL, 0 }, 205 { CKA_VALIDATION_AUTHORITY_TYPE, NULL, 0 }, 206 { CKA_VALIDATION_TYPE, NULL, 0 }, 207 { CKA_VALIDATION_VERSION, NULL, 0 }, 208 { CKA_VALIDATION_LEVEL, NULL, 0 }, 209 { CKA_VALIDATION_FLAG, NULL, 0 }, 210 { CKA_VALIDATION_COUNTRY, NULL, 0 }, 211 { CKA_VALIDATION_CERTIFICATE_IDENTIFIER, NULL, 0 }, 212 { CKA_VALIDATION_CERTIFICATE_URI, NULL, 0 }, 213 { CKA_VALIDATION_PROFILE, NULL, 0 }, 214 { CKA_VALIDATION_VENDOR_URI, NULL, 0 }, 215 }; 216 attributeTag validation_tags[] = { 217 { "Validation Module ID", tagUtf8 }, 218 { "Validation Authority Type", tagValidationAuthorityType }, 219 { "Validation Type", tagValidationType }, 220 { "Validation Version", tagVersion }, 221 { "Validation Level", tagULong }, 222 { "Validation Flag", tagULongFlag }, 223 { "Validation Country", tagUtf8 }, 224 { "Validation Certificate Identifier", tagUtf8 }, 225 { "Validation Certificate URI", tagUtf8 }, 226 { "Validation Certificate Profile", tagUtf8 }, 227 { "Validation Vendor URI", tagUtf8 }, 228 }; 229 230 CK_ATTRIBUTE nss_validation_template[] = { 231 { CKA_NSS_VALIDATION_TYPE, NULL, 0 }, 232 { CKA_NSS_VALIDATION_VERSION, NULL, 0 }, 233 { CKA_NSS_VALIDATION_LEVEL, NULL, 0 }, 234 { CKA_NSS_VALIDATION_MODULE_ID, NULL, 0 } 235 }; 236 attributeTag nss_validation_tags[] = { 237 { "Validation Type", tagULong }, 238 { "Validation Version", tagVersion }, 239 { "Validation Level", tagULong }, 240 { "Validation Module ID", tagUtf8 }, 241 }; 242 243 #ifdef _CRTDBG_MAP_ALLOC 244 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 245 #endif 246 247 validation.numCommands = 0; 248 validation.commands = 0; 249 validation.numOptions = PR_ARRAY_SIZE(validation_options); 250 validation.options = validation_options; 251 252 progName = strrchr(argv[0], '/'); 253 progName = progName ? progName + 1 : argv[0]; 254 255 rv = SECU_ParseCommandLine(argc, argv, progName, &validation); 256 257 if (rv != SECSuccess) 258 Usage(); 259 260 if (validation.options[opt_ForceVendor].activated && 261 validation.options[opt_ForcePKCS11].activated) { 262 fprintf(stderr, "-o and -p are mutually exclusive\n"); 263 Usage(); 264 } 265 266 debug = validation.options[opt_Debug].activated; 267 268 slotname = SECU_GetOptionArg(&validation, opt_TokenName); 269 270 if (validation.options[opt_SlotPWFile].activated) { 271 slotPw.source = PW_FROMFILE; 272 slotPw.data = PORT_Strdup(validation.options[opt_SlotPWFile].arg); 273 } 274 275 if (validation.options[opt_SlotPW].activated) { 276 slotPw.source = PW_PLAINTEXT; 277 slotPw.data = PORT_Strdup(validation.options[opt_SlotPW].arg); 278 } 279 280 if (validation.options[opt_CertDir].activated) { 281 nssdir = validation.options[opt_CertDir].arg; 282 } 283 if (validation.options[opt_DBPrefix].activated) { 284 dbprefix = validation.options[opt_DBPrefix].arg; 285 } 286 287 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 288 if (nssdir == NULL && NSS_NoDB_Init("") == SECSuccess) { 289 rv = SECSuccess; 290 /* if the system isn't already in FIPS mode, we need 291 * to switch to FIPS mode */ 292 if (!PK11_IsFIPS()) { 293 /* flip to FIPS mode */ 294 SECMODModule *module = SECMOD_GetInternalModule(); 295 rv = SECMOD_DeleteInternalModule(module->commonName); 296 } 297 } else if (nssdir != NULL) { 298 rv = NSS_Initialize(nssdir, dbprefix, dbprefix, "secmod.db", 0); 299 } 300 if (rv != SECSuccess) { 301 SECU_PrintPRandOSError(progName); 302 local_errno = -1; 303 goto done; 304 } 305 306 if (!slotname || PL_strcmp(slotname, "internal") == 0) 307 slot = PK11_GetInternalKeySlot(); 308 else 309 slot = PK11_FindSlotByName(slotname); 310 311 if (!slot) { 312 SECU_PrintError(progName, "Invalid slot \"%s\"", 313 slotname ? "internal" : slotname); 314 local_errno = ERR_PK11GETSLOT; 315 goto done; 316 } 317 if (validation.options[opt_ForceVendor].activated) { 318 rv = dump_validations(CKO_NSS_VALIDATION, 319 nss_validation_template, 320 PR_ARRAY_SIZE(nss_validation_template), 321 nss_validation_tags, 322 slot); 323 } else if (validation.options[opt_ForcePKCS11].activated) { 324 rv = dump_validations(CKO_VALIDATION, 325 validation_template, 326 PR_ARRAY_SIZE(validation_template), 327 validation_tags, 328 slot); 329 } else if (PK11_CheckPKCS11Version(slot, 3, 2, PR_FALSE) >= 0) { 330 rv = dump_validations(CKO_VALIDATION, 331 validation_template, 332 PR_ARRAY_SIZE(validation_template), 333 validation_tags, 334 slot); 335 } else { 336 rv = dump_validations(CKO_NSS_VALIDATION, 337 nss_validation_template, 338 PR_ARRAY_SIZE(nss_validation_template), 339 nss_validation_tags, 340 slot); 341 } 342 343 if (rv != SECSuccess) { 344 SECU_PrintPRandOSError(progName); 345 local_errno = -1; 346 } 347 348 done: 349 if (slotPw.data != NULL) 350 PORT_ZFree(slotPw.data, PL_strlen(slotPw.data)); 351 if (p12FilePw.data != NULL) 352 PORT_ZFree(p12FilePw.data, PL_strlen(p12FilePw.data)); 353 if (slotname) { 354 PORT_Free(slotname); 355 } 356 if (slot) 357 PK11_FreeSlot(slot); 358 if (NSS_Shutdown() != SECSuccess) { 359 local_errno = 1; 360 } 361 PL_ArenaFinish(); 362 PR_Cleanup(); 363 return local_errno; 364 }