Ejemplo n.º 1
0
/**
 * Reads the specified number of bytes from the file pointer and
 * stores them in the passed buffer.
 *
 * @param  fp     The file pointer to read from.
 * @param  buffer The buffer to store the read results.
 * @param  size   The number of bytes to read, buffer must be 
 *                at least of this size.
 * @param  ctxs   Pointer to the first element in an array of verify context.
 * @param  count  The number of elements in ctxs
 * @param  err    The name of what is being written to in case of error.
 * @return  0 on success
 *         -1 on read error
 *         -2 on verify update error
*/
int
ReadAndUpdateVerifyContext(FILE *fp, 
                           void *buffer,
                           uint32_t size, 
                           CryptoX_SignatureHandle *ctxs,
                           uint32_t count,
                           const char *err) 
{
  uint32_t k;
  if (!fp || !buffer || !ctxs || count == 0 || !err) {
    fprintf(stderr, "ERROR: Invalid parameter specified.\n");
    return CryptoX_Error;
  }

  if (!size) { 
    return CryptoX_Success;
  }

  if (fread(buffer, size, 1, fp) != 1) {
    fprintf(stderr, "ERROR: Could not read %s\n", err);
    return CryptoX_Error;
  }

  for (k = 0; k < count; k++) {
    if (CryptoX_Failed(CryptoX_VerifyUpdate(&ctxs[k], buffer, size))) {
      fprintf(stderr, "ERROR: Could not update verify context for %s\n", err);
      return -2;
    }
  }
  return CryptoX_Success;
}
Ejemplo n.º 2
0
/**
 * Reads the specified number of bytes from the file pointer and
 * stores them in the passed buffer.
 *
 * @param  fp     The file pointer to read from.
 * @param  buffer The buffer to store the read results.
 * @param  size   The number of bytes to read, buffer must be 
 *                at least of this size.
 * @param  ctx    The verify context.
 * @param  err    The name of what is being written to in case of error.
 * @return  0 on success
 *         -1 on read error
 *         -2 on verify update error
*/
int
ReadAndUpdateVerifyContext(FILE *fp, 
                           void *buffer,
                           PRUint32 size, 
                           CryptoX_SignatureHandle *ctx,
                           const char *err) 
{
  if (!fp || !buffer || !ctx || !err) {
    fprintf(stderr, "ERROR: Invalid parameter specified.\n");
    return CryptoX_Error;
  }

  if (!size) { 
    return CryptoX_Success;
  }

  if (fread(buffer, size, 1, fp) != 1) {
    fprintf(stderr, "ERROR: Could not read %s\n", err);
    return CryptoX_Error;
  }

  if (CryptoX_Failed(CryptoX_VerifyUpdate(ctx, buffer, size))) {
    fprintf(stderr, "ERROR: Could not update verify context for %s\n", err);
    return -2;
  }
  return CryptoX_Success;
}
Ejemplo n.º 3
0
/**
 * Verifies a MAR file by verifying each signature with the corresponding
 * certificate. That is, the first signature will be verified using the first
 * certificate given, the second signature will be verified using the second
 * certificate given, etc. The signature count must exactly match the number of
 * certificates given, and all signature verifications must succeed.
 * 
 * @param  fp                   An opened MAR file handle
 * @param  provider             A library provider
 * @param  keys                 A pointer to the first element in an
 *                              array of keys.
 * @param  extractedSignatures  Pointer to the first element in an array
 *                              of extracted signatures.
 * @param  signatureCount       The number of signatures in the MAR file
 * @param numVerified           Out parameter which will be filled with
 *                              the number of verified signatures.
 *                              This information can be useful for printing
 *                              error messages.
 * @return 0 on success, *numVerified == signatureCount.
*/
int
mar_verify_signatures_for_fp(FILE *fp,
                             CryptoX_ProviderHandle provider,
                             CryptoX_PublicKey *keys,
                             const uint8_t * const *extractedSignatures,
                             uint32_t signatureCount,
                             uint32_t *numVerified)
{
  CryptoX_SignatureHandle signatureHandles[MAX_SIGNATURES];
  char buf[BLOCKSIZE];
  uint32_t signatureLengths[MAX_SIGNATURES];
  uint32_t i;
  int rv = CryptoX_Error;

  memset(signatureHandles, 0, sizeof(signatureHandles));
  memset(signatureLengths, 0, sizeof(signatureLengths));

  if (!extractedSignatures || !numVerified) {
    fprintf(stderr, "ERROR: Invalid parameter specified.\n");
    goto failure;
  }

  *numVerified = 0;

  /* This function is only called when we have at least one signature,
     but to protected against future people who call this function we
     make sure a non zero value is passed in. 
   */
  if (!signatureCount) {
    fprintf(stderr, "ERROR: There must be at least one signature.\n");
    goto failure;
  }

  for (i = 0; i < signatureCount; i++) {
    if (CryptoX_Failed(CryptoX_VerifyBegin(provider,
                                           &signatureHandles[i], &keys[i]))) {
      fprintf(stderr, "ERROR: Could not initialize signature handle.\n");
      goto failure;
    }
  }

  /* Skip to the start of the file */
  if (fseeko(fp, 0, SEEK_SET)) {
    fprintf(stderr, "ERROR: Could not seek to start of the file\n");
    goto failure;
  }

  /* Bytes 0-3: MAR1
     Bytes 4-7: index offset 
     Bytes 8-15: size of entire MAR
   */
  if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp, buf, 
                                                SIGNATURE_BLOCK_OFFSET +
                                                sizeof(uint32_t),
                                                signatureHandles,
                                                signatureCount,
                                                "signature block"))) {
    goto failure;
  }

  /* Read the signature block */
  for (i = 0; i < signatureCount; i++) {
    /* Get the signature algorithm ID */
    if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp,
                                                  &buf, 
                                                  sizeof(uint32_t),
                                                  signatureHandles,
                                                  signatureCount,
                                                  "signature algorithm ID"))) {
      goto failure;
    }

    if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp, 
                                                  &signatureLengths[i],
                                                  sizeof(uint32_t), 
                                                  signatureHandles,
                                                  signatureCount,
                                                  "signature length"))) {
      goto failure;
    }
    signatureLengths[i] = ntohl(signatureLengths[i]);
    if (signatureLengths[i] > MAX_SIGNATURE_LENGTH) {
      fprintf(stderr, "ERROR: Embedded signature length is too large.\n");
      goto failure;
    }

    /* Skip past the signature itself as those are not included */
    if (fseeko(fp, signatureLengths[i], SEEK_CUR)) {
      fprintf(stderr, "ERROR: Could not seek past signature.\n");
      goto failure;
    }
  }

  /* Read the rest of the file after the signature block */
  while (!feof(fp)) {
    int numRead = fread(buf, 1, BLOCKSIZE , fp);
    if (ferror(fp)) {
      fprintf(stderr, "ERROR: Error reading data block.\n");
      goto failure;
    }

    for (i = 0; i < signatureCount; i++) {
      if (CryptoX_Failed(CryptoX_VerifyUpdate(&signatureHandles[i],
                                              buf, numRead))) {
        fprintf(stderr, "ERROR: Error updating verify context with"
                        " data block.\n");
        goto failure;
      }
    }
  }

  /* Verify the signatures */
  for (i = 0; i < signatureCount; i++) {
    if (CryptoX_Failed(CryptoX_VerifySignature(&signatureHandles[i],
                                               &keys[i],
                                               extractedSignatures[i],
                                               signatureLengths[i]))) {
      fprintf(stderr, "ERROR: Error verifying signature.\n");
      goto failure;
    }
    ++*numVerified;
  }

  rv = CryptoX_Success;
failure:
  for (i = 0; i < signatureCount; i++) {
    CryptoX_FreeSignatureHandle(&signatureHandles[i]);
  }

  return rv;
}
Ejemplo n.º 4
0
/**
 * Verifies if a specific signature ID matches the extracted signature.
 * 
 * @param  fp                   An opened MAR file handle
 * @param  provider             A library provider
 * @param  key                  The public key to use to verify the MAR
 * @param  signatureCount        The number of signatures in the MAR file
 * @param  extractedSignature    The signature that should be verified
 * @return 0 on success
*/
int
mar_verify_signature_for_fp(FILE *fp, 
                            CryptoX_ProviderHandle provider, 
                            CryptoX_PublicKey key, 
                            PRUint32 signatureCount,
                            char *extractedSignature) {
  CryptoX_SignatureHandle signatureHandle;
  char buf[BLOCKSIZE];
  PRUint32 signatureLen;
  PRUint32 i;

  if (!extractedSignature) {
    fprintf(stderr, "ERROR: Invalid parameter specified.\n");
    return CryptoX_Error;
  }

  /* This function is only called when we have at least one signature,
     but to protected against future people who call this function we
     make sure a non zero value is passed in. 
   */
  if (!signatureCount) {
    fprintf(stderr, "ERROR: There must be at least one signature.\n");
    return CryptoX_Error;
  }

  CryptoX_VerifyBegin(provider, &signatureHandle, &key);

  /* Skip to the start of the file */
  if (fseeko(fp, 0, SEEK_SET)) {
    fprintf(stderr, "ERROR: Could not seek to start of the file\n");
    return CryptoX_Error;
  }

  /* Bytes 0-3: MAR1
     Bytes 4-7: index offset 
     Bytes 8-15: size of entire MAR
   */
  if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp, buf, 
                                                SIGNATURE_BLOCK_OFFSET +
                                                sizeof(PRUint32),
                                                &signatureHandle,
                                                "signature block"))) {
    return CryptoX_Error;
  }

  for (i = 0; i < signatureCount; i++) {
    /* Get the signature algorithm ID */
    if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp,
                                                  &buf, 
                                                  sizeof(PRUint32),
                                                  &signatureHandle, 
                                                  "signature algorithm ID"))) {
        return CryptoX_Error;
    }

    if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp, 
                                                  &signatureLen, 
                                                  sizeof(PRUint32), 
                                                  &signatureHandle, 
                                                  "signature length"))) {
      return CryptoX_Error;
    }
    signatureLen = ntohl(signatureLen);

    /* Skip past the signature itself as those are not included */
    if (fseeko(fp, signatureLen, SEEK_CUR)) {
      fprintf(stderr, "ERROR: Could not seek past signature.\n");
      return CryptoX_Error;
    }
  }

  while (!feof(fp)) {
    int numRead = fread(buf, 1, BLOCKSIZE , fp);
    if (ferror(fp)) {
      fprintf(stderr, "ERROR: Error reading data block.\n");
      return CryptoX_Error;
    }

    if (CryptoX_Failed(CryptoX_VerifyUpdate(&signatureHandle, 
                                            buf, numRead))) {
      fprintf(stderr, "ERROR: Error updating verify context with"
                      " data block.\n");
      return CryptoX_Error;
    }
  }

  if (CryptoX_Failed(CryptoX_VerifySignature(&signatureHandle, 
                                             &key,
                                             extractedSignature, 
                                             signatureLen))) {
    fprintf(stderr, "ERROR: Error verifying signature.\n");
    return CryptoX_Error;
  }

  return CryptoX_Success;
}