Last active
June 8, 2017 07:19
-
-
Save frasertweedale/c00fac99c992a82e0a3fa4aa83d407b4 to your computer and use it in GitHub Desktop.
NSS test programs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <nss.h> | |
| #include <plarena.h> | |
| #include <nspr.h> | |
| #include <key.h> | |
| #include <secmod.h> | |
| #include <pk11func.h> | |
| #include <cert.h> | |
| #include <certdb.h> | |
| #include <secasn1.h> | |
| #include <errno.h> | |
| #include <fcntl.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| char *pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) { | |
| printf("pwcb; arg: %p '%s'\n", arg, (char *) arg); | |
| return (char *) arg; | |
| } | |
| int main(int argc, char **argv) { | |
| if (argc < 6) { | |
| printf("usage: test EPKI-OFFSET EPKI-LEN SPKI-OFFSET SPKI-LEN P12-FILE\n"); | |
| return 1; | |
| } | |
| int epki_offset = atoi(argv[1]); | |
| int epki_length = atoi(argv[2]); | |
| int spki_offset = atoi(argv[3]); | |
| int spki_length = atoi(argv[4]); | |
| PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); | |
| SECStatus secrv = NSS_Initialize("nssdb2", "", "", "secmod.db", 0); | |
| if (secrv != SECSuccess) { | |
| printf("failed to init NSS\n"); | |
| return 1; | |
| } | |
| PK11_SetPasswordFunc(pwcb); | |
| printf("opening '%s'\n", argv[5]); | |
| int fd = open(argv[5], O_RDONLY); | |
| if (fd < 0) { | |
| printf("failed to open p12 file: %s\n", strerror(errno)); | |
| return 1; | |
| } | |
| printf("reading epki from p12 file\n"); | |
| unsigned char epki_bytes[epki_length]; | |
| lseek(fd, epki_offset, SEEK_SET); | |
| int n = read(fd, epki_bytes, epki_length); | |
| if (n != epki_length) { | |
| printf("read %d bytes instead of expected %d bytes\n", | |
| n, epki_length); | |
| } | |
| printf("reading spki from p12 file\n"); | |
| unsigned char spki_bytes[spki_length]; | |
| lseek(fd, spki_offset, SEEK_SET); | |
| n = read(fd, spki_bytes, spki_length); | |
| if (n != spki_length) { | |
| printf("read %d bytes instead of expected %d bytes\n", | |
| n, spki_length); | |
| } | |
| // decode EncryptedPrivateKeyInfo | |
| SECItem epkiItem; | |
| epkiItem.data = epki_bytes; | |
| epkiItem.len = epki_length; | |
| SECKEYEncryptedPrivateKeyInfo epki; | |
| PORT_Memset(&epki, 0, sizeof(epki)); | |
| if (SEC_ASN1DecodeItem( | |
| NULL, | |
| &epki, | |
| SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), | |
| &epkiItem | |
| ) != SECSuccess) { | |
| // TODO throw | |
| printf("failed to decode epki"); | |
| return 1; | |
| } | |
| printf("decoded epki\n"); | |
| printf(" encryptedData len: %d\n", epki.encryptedData.len); | |
| printf(" algorithm algorithm len: %d\n", epki.algorithm.algorithm.len); | |
| printf(" algorithm parameters len: %d\n", epki.algorithm.parameters.len); | |
| // get password | |
| unsigned char pw[] = | |
| { 0, '4', 0, 'm', 0, 'e', 0, '2' | |
| , 0, 'T', 0, 'e', 0, 's', 0, 't' | |
| , 0, 0 | |
| }; | |
| SECItem pwItem; | |
| pwItem.data = pw; | |
| pwItem.len = sizeof(pw); | |
| printf("prepared password; len: %d\n", pwItem.len); | |
| /* | |
| printf("vvv\n"); | |
| for (int i = 0; i < pwItem.len; i++) { | |
| printf("%d\n", pw[i]); | |
| } | |
| printf("^^^\n"); | |
| */ | |
| // get public key value | |
| SECItem spkiItem; | |
| spkiItem.data = spki_bytes; | |
| spkiItem.len = spki_length; | |
| CERTSubjectPublicKeyInfo spki; | |
| PORT_Memset(&spki, 0, sizeof(spki)); | |
| if (SEC_ASN1DecodeItem( | |
| NULL, | |
| &spki, | |
| SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate), | |
| &spkiItem | |
| ) != SECSuccess) { | |
| // TODO throw | |
| printf("failed to decode spki\n"); | |
| return 1; | |
| } | |
| printf("decoded spki\n"); | |
| SECKEYPublicKey *pubKey = SECKEY_ExtractPublicKey(&spki); | |
| if (pubKey == NULL) { | |
| // TODO throw | |
| printf("failed to get pubkey\n"); | |
| return 1; | |
| } | |
| printf("extracted public key\n"); | |
| printf(" key type: %d\n", pubKey->keyType); | |
| SECItem *pubValue; | |
| switch (pubKey->keyType) { | |
| case dsaKey: | |
| pubValue = &pubKey->u.dsa.publicValue; | |
| break; | |
| case dhKey: | |
| pubValue = &pubKey->u.dh.publicValue; | |
| break; | |
| case rsaKey: | |
| pubValue = &pubKey->u.rsa.modulus; | |
| break; | |
| case ecKey: | |
| pubValue = &pubKey->u.ec.publicValue; | |
| break; | |
| default: | |
| pubValue = NULL; | |
| } | |
| if (pubValue != NULL) { | |
| printf(" pubValue len: %d\n", pubValue->len); | |
| printf(" pubValue type: %d\n", pubValue->type); // should be 10 | |
| printf(" pubValue->data[1] (n?): %c\n", pubValue->data[1]); | |
| printf(" pubValue->data[80] (L?): %c\n", pubValue->data[80]); | |
| } | |
| // prepare nickname | |
| unsigned char nick[] = "mynickname"; | |
| SECItem nickItem; | |
| nickItem.data = nick; | |
| nickItem.len = sizeof(nick); | |
| printf("prepared nickname\n"); | |
| // get slot | |
| PK11SlotInfo *slot = PK11_GetInternalKeySlot(); | |
| if (slot == NULL) { | |
| printf("failed to get slot\n"); | |
| return 1; | |
| } | |
| printf("got slot!\n"); | |
| // authenticate to slot | |
| secrv = PK11_Authenticate(slot, PR_TRUE, strdup("4me2Test")); | |
| if (secrv != SECSuccess) { | |
| printf("failed to authenticate to slot\n"); | |
| return 1; | |
| } | |
| printf("authenticated to slot\n"); | |
| // perform import | |
| SECStatus result = PK11_ImportEncryptedPrivateKeyInfo( | |
| slot, &epki, &pwItem, &nickItem, pubValue, | |
| PR_TRUE, // isperm | |
| PR_TRUE, // isprivate | |
| pubKey->keyType, | |
| 198, // keyUsage | |
| NULL // wincx | |
| ); | |
| printf("returned from PK11_ImportEncryptedPrivateKeyInfo\n"); | |
| if (result != SECSuccess) { | |
| printf("Failed to import EncryptedPrivateKeyInfo to token\n"); | |
| return 1; | |
| } | |
| return 0; | |
| printf("bye!\n"); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <nss.h> | |
| #include <pk11pub.h> | |
| unsigned char * hexencode(unsigned char *in, unsigned int len); | |
| int main(int argc, char **argv) { | |
| SECStatus rv; | |
| NSS_NoDB_Init(NULL); | |
| unsigned char saltBytes[] = {1, 1, 1, 1}; | |
| SECItem salt; | |
| salt.data = saltBytes; | |
| salt.len = 4; | |
| unsigned char saltBytes16[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; | |
| SECItem salt16; | |
| salt16.data = saltBytes16; | |
| salt16.len = 16; | |
| SECAlgorithmID *algidDESUnk = PK11_CreatePBEV2AlgorithmID( | |
| SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, | |
| SEC_OID_UNKNOWN, | |
| SEC_OID_UNKNOWN, | |
| 0, | |
| 1, | |
| &salt | |
| ); | |
| SECAlgorithmID *algidDES = PK11_CreatePBEV2AlgorithmID( | |
| SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, | |
| SEC_OID_DES_EDE3_CBC, | |
| SEC_OID_HMAC_SHA1, | |
| 0, | |
| 1, | |
| &salt | |
| ); | |
| SECAlgorithmID *algidAES = PK11_CreatePBEV2AlgorithmID( | |
| SEC_OID_AES_256_CBC, | |
| SEC_OID_UNKNOWN, | |
| SEC_OID_UNKNOWN, | |
| 32, | |
| 2000, | |
| &salt16 | |
| ); | |
| SECAlgorithmID *algid = algidAES; | |
| if (algid == NULL) { | |
| fprintf(stderr, "failed to construct AlgorithmIdentifier\n"); | |
| return(1); | |
| } | |
| SECItem *derAlgid = SEC_ASN1EncodeItem( | |
| NULL, NULL, algid, SEC_ASN1_GET(SECOID_AlgorithmIDTemplate)); | |
| if (derAlgid != NULL) { | |
| //fprintf(stderr, "result: %p ; len = %u \n", derAlgid, derAlgid->len); | |
| //write(STDOUT_FILENO, derAlgid->data, derAlgid->len); | |
| } | |
| SECItem password = { siBuffer, "4me2Test", 8 }; | |
| //fprintf(stderr, "%s\n", hexencode(password.data, password.len)); | |
| PK11SlotInfo *slot = PK11_GetBestSlot(SEC_OID_AES_256_CBC, NULL); | |
| PK11SymKey *key = PK11_PBEKeyGen(slot, algid, &password, PR_FALSE, NULL); | |
| if (key == NULL) { | |
| fprintf(stderr, "Key generation/derivation failed\n"); | |
| return 1; | |
| } | |
| /* | |
| if (SECFailure == PK11_ExtractKeyValue(key)) { | |
| fprintf(stderr, "Key extraction failed\n"); | |
| return 1; | |
| } | |
| SECItem *keydata = PK11_GetKeyData(key); | |
| fprintf(stderr, "derived key (%u bytes): %s\n", keydata->len, hexencode(keydata->data, keydata->len)); | |
| */ | |
| CK_MECHANISM_TYPE keyMech = PK11_GetMechanism(key); | |
| CK_MECHANISM_TYPE keyType = PK11_GetKeyType(keyMech, 0); | |
| fprintf(stderr, "key mech: 0x%x\n", keyMech); | |
| fprintf(stderr, "key type: 0x%x\n", keyType); | |
| fprintf(stderr, "encrypting the easy way\n"); | |
| char *msg = "Hello, world!"; | |
| char msgEnc[200]; | |
| unsigned int len; | |
| SECItem *cryptoParams; | |
| CK_MECHANISM_TYPE cryptoMechType = | |
| PK11_GetPBECryptoMechanism(algid, &cryptoParams, &password); | |
| cryptoMechType = PK11_GetPadMechanism(cryptoMechType); | |
| fprintf(stderr, "enc mech type: 0x%x\n", cryptoMechType); | |
| rv = PK11_Encrypt( | |
| key, cryptoMechType, cryptoParams, | |
| msgEnc, &len, sizeof(msgEnc), | |
| msg, strlen(msg) | |
| ); | |
| if (rv != SECSuccess) | |
| fprintf(stderr, "first enc failed"); | |
| fprintf(stderr, "first enc len: %u\n", len); | |
| fprintf(stderr, "encrypting the hard way\n"); | |
| PK11Context *ctx = PK11_CreateContextBySymKey( | |
| cryptoMechType, CKA_ENCRYPT, key, cryptoParams); | |
| if (ctx == NULL) { | |
| fprintf(stderr, "null context\n"); | |
| return 1; | |
| } | |
| char msgEnc2[200]; | |
| rv = PK11_CipherOp(ctx, msgEnc2, &len, sizeof(msgEnc2), msg, strlen(msg)); | |
| if (rv != SECSuccess) | |
| fprintf(stderr, "second enc update failed"); | |
| fprintf(stderr, "second enc len: %u\n", len); | |
| rv = PK11_DigestFinal(ctx, msgEnc2, &len, sizeof(msgEnc2)); | |
| if (rv != SECSuccess) | |
| fprintf(stderr, "second enc finalise failed"); | |
| fprintf(stderr, "second enc len: %u\n", len); | |
| fprintf(stderr, "memcmp: %d\n", memcmp(msgEnc, msgEnc2, len)); | |
| PK11_FreeSlot(slot); | |
| return 0; | |
| } | |
| unsigned char * hexencode(unsigned char *in, unsigned int len) { | |
| unsigned char *s = "0123456789abcdef"; | |
| unsigned char *out = calloc(len * 2 + 1, sizeof(char)); | |
| for (unsigned int i = 0; i < len; i++) { | |
| out[i * 2] = s[in[i] >> 4]; | |
| out[i * 2 + 1] = s[in[i] & 15]; | |
| } | |
| return out; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment