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 dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto