Skip to content

Instantly share code, notes, and snippets.

@frasertweedale
Last active June 8, 2017 07:19
Show Gist options
  • Save frasertweedale/c00fac99c992a82e0a3fa4aa83d407b4 to your computer and use it in GitHub Desktop.
Save frasertweedale/c00fac99c992a82e0a3fa4aa83d407b4 to your computer and use it in GitHub Desktop.
NSS test programs
#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");
}
#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