I'm trying to verify the signature of a file I've signed but I don't
understand where to get the sigAlgorithm and hash to pass to
VFY_CreateContextWithAlgorithmID. I've googled looking for some sample
code using the VFY_ apis to verify signatures but I haven't found
anything that I could build off of. Shouldn't I be able to get these
from the public key and/or signature itself?
int spl_nssSignSHA256(const char *certNickname, const char *certpw,
const char *certdbpw, const char *certDir, const char *data, const
char *filename, unsigned char **signature, char **error)
{
int result = 0;
CERTCertificate *cert = NULL;
SECKEYPrivateKey *pvtkey = NULL;
unsigned char hash_buf[SHA256_LENGTH];
SECItem hash, sign;
PK11Context *hashcx = NULL;
SECStatus rc;
if ((data != NULL && filename != NULL) ||
(data == NULL && filename == NULL)) {
asprintf(error, "Error invalid arguments");
result = -1;
goto cleanup;
}
hash.len = sizeof(hash_buf); hash.data = hash_buf;
if (certDir != NULL)
rc = NSS_Init(certDir);
else
rc = NSS_Init(SPL_NSSCERTDIR);
if (rc != SECSuccess) {
asprintf(error, "Error initializing NSS (%d)",
PR_GetError());
result = -1;
goto cleanup;
}
PK11_SetPasswordFunc(spl_nssPasswdCB);
cert = PK11_FindCertFromNickname(certNickname, (void *)certdbpw);
if (cert == NULL) {
asprintf(error, "Couldn't find cert for %s in NSS db (err %d)",
certNickname,
PR_GetError());
result = -1;
goto cleanup;
}
pvtkey = PK11_FindKeyByAnyCert(cert, (void *)certpw);
if (pvtkey == NULL) {
asprintf(error, "Couldn't find private key for cert %s (err
%d)",
certNickname,
PR_GetError());
result = -1;
goto cleanup;
}
hashcx = PK11_CreateDigestContext(SEC_OID_SHA256);
if (hashcx == NULL) {
asprintf(error, "Error creating SHA526 digest (%d)",
PR_GetError());
result = -1;
goto cleanup;
}
if (filename != NULL) {
int fd = 0;
int bytesRead = 0;
int buflen = 1024;
char *buf = (char *)malloc(buflen);
if ((fd = open(filename, O_RDONLY)) < 0) {
asprintf(error, "Error opening %s - %s",
filename,
strerror(errno));
result = -1;
goto cleanup;
}
while ((bytesRead = read(fd, buf, buflen)) > 0) {
PK11_DigestOp(hashcx, (const unsigned char *)buf,
bytesRead);
}
free(buf);
close(fd);
if (bytesRead < 0) {
asprintf(error, "Error reading %s - %s",
filename,
strerror(errno));
result = -1;
goto cleanup;
}
}
else
PK11_DigestOp(hashcx, (const unsigned char *)data,
strlen(data));
PK11_DigestFinal(hashcx, hash.data, &hash.len, hash.len);
if (hash.len != SHA256_LENGTH) {
asprintf(error, "Digest length was not correct");
result = -1;
goto cleanup;
}
sign.len = PK11_SignatureLen(pvtkey);
if (sign.len <= 0) {
asprintf(error, "Invalid private key");
result = -1;
goto cleanup;
}
sign.data = (unsigned char *)malloc(sign.len);
if (sign.data == NULL) {
perror("Error allocating memory");
result = -1;
goto cleanup;
}
/* sign the hash */
rc = PK11_Sign(pvtkey, &sign, &hash);
if (rc != SECSuccess) {
asprintf(error, "Error signing data %d",
PR_GetError());
free(sign.data);
result = -1;
goto cleanup;
}
*signature = sign.data;
result = 0;
cleanup:
if (cert)
CERT_DestroyCertificate(cert);
if (pvtkey)
SECKEY_DestroyPrivateKey(pvtkey);
if (hashcx)
PK11_DestroyContext(hashcx, PR_TRUE);
NSS_Shutdown();
return result;
}
int spl_nssVerifySignature(const char *certNickname, const char
*certdbpw, const char *certDir, const char *data, const char
*filename, unsigned char *signature, char **error)
{
int result = 0;
CERTCertificate *cert = NULL;
CERTSubjectPublicKeyInfo *spki;
SECKEYPublicKey *pubkey = NULL;
unsigned char hash_buf[SHA256_LENGTH];
SECItem hash, sign;
SECStatus rc;
VFYContext vfy_context;
if ((data != NULL && filename != NULL) ||
(data == NULL && filename == NULL)) {
asprintf(error, "Error invalid arguments");
result = -1;
goto cleanup;
}
hash.len = sizeof(hash_buf); hash.data = hash_buf;
if (certDir != NULL)
rc = NSS_Init(certDir);
else
rc = NSS_Init(SPL_NSSCERTDIR);
if (rc != SECSuccess) {
asprintf(error, "Error initializing NSS (%d)",
PR_GetError());
result = -1;
goto cleanup;
}
PK11_SetPasswordFunc(spl_nssPasswdCB);
cert = PK11_FindCertFromNickname(certNickname, (void *)certdbpw);
if (cert == NULL) {
asprintf(error, "Couldn't find cert for %s in NSS db (err %d)",
certNickname,
PR_GetError());
result = -1;
goto cleanup;
}
spki = &cert->subjectPublicKeyInfo;
pubkey = CERT_ExtractPublicKey(cert);
if (pubkey == NULL) {
asprintf(error, "Couldn't extract public key from cert %s (err
%d)",
certNickname,
PR_GetError());
result = -1;
goto cleanup;
}
/* SEC_OID_PKCS1_RSA_ENCRYPTION */
PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
result = -1;
goto cleanup;
}
SECAlgorithmID sig_alg_id;
/*
SECItem sig_alg_der;
sig_alg_der.type = siBuffer;
sig_alg_der.data = SEC_OID_PKCS1_RSA_ENCRYPTION; ????
sig_alg_der.len = signature_algorithm_len;
rc = SEC_QuickDERDecodeItem(arena, &sig_alg_id,
SECOID_AlgorithmIDTemplate,
&sig_alg_der);
if (rc != SECSuccess) {
goto cleanup;
}
*/
SECItem sig;
sig.type = siBuffer;
sig.data = signature;
sig.len = strlen(signature);
SECOidTag hash_alg_tag;
vfy_context = VFY_CreateContextWithAlgorithmID(pubkey, &sig,
&sig_alg_id,
&hash_alg_tag,
NULL);
PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id.
if (!vfy_context) {
result = -1;
goto cleanup;
}
rc = VFY_Begin(vfy_context);
if (rc != SECSuccess) {
result = -1;
goto cleanup;
}
if (filename != NULL) {
int fd = 0;
int bytesRead = 0;
int buflen = 1024;
char *buf = (char *)malloc(buflen);
if ((fd = open(filename, O_RDONLY)) < 0) {
asprintf(error, "Error opening %s - %s",
filename,
strerror(errno));
result = -1;
goto cleanup;
}
while ((bytesRead = read(fd, buf, buflen)) > 0) {
rc = VFY_Update(vfy_context, (const unsigned char
*)buf, bytesRead);
}
free(buf);
close(fd);
if (bytesRead < 0) {
asprintf(error, "Error reading %s - %s",
filename,
strerror(errno));
result = -1;
goto cleanup;
}
}
else
rc = VFY_Update(vfy_context, (const unsigned char *)data,
strlen);
rc = VFY_End(vfy_context);
if (rc != SECSuccess) {
asprintf(error, "Signature verification failed");
result = -1;
goto cleanup;
}
result = 0;
cleanup:
if (cert)
CERT_DestroyCertificate(cert);
if (pubkey)
SECKEY_DestroyPublicKey(pubkey);
if (vfy_context != NULL)
VFY_DestroyContext(vfy_context, PR_TRUE);
if (arena)
PORT_FreeArena(arena, PR_TRUE);
NSS_Shutdown();
return result;
}
--
dev-tech-crypto mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-crypto