예제 #1
0
/*
 * Verify the signature on an assertion.
 */
int
kn_verify_assertion(char *buf, int len)
{
    struct assertion *as;
    int res;

    keynote_errno = 0;
    as = keynote_parse_assertion(buf, len, ASSERT_FLAG_SIGVER);
    if (as == NULL)
      return -1;

    res = keynote_sigverify_assertion(as);
    keynote_free_assertion(as);
    return res;
}
예제 #2
0
/*
 * Sign an assertion.
 */
static char *
keynote_sign_assertion(struct assertion *as, char *sigalg, void *key,
		       int keyalg, int verifyflag)
{
    int slen, i, hashlen = 0, hashtype, alg, encoding, internalenc;
    unsigned char *sig = NULL, *finalbuf = NULL;
    unsigned char res2[LARGEST_HASH_SIZE], *sbuf = NULL;
    BIO *biokey = NULL;
    DSA *dsa = NULL;
    RSA *rsa = NULL;
    SHA_CTX shscontext;
    MD5_CTX md5context;
    int len;

    if (as->as_signature_string_s == NULL ||
	as->as_startofsignature == NULL ||
	as->as_allbutsignature == NULL ||
	as->as_allbutsignature - as->as_startofsignature <= 0 ||
	as->as_authorizer == NULL ||
	key == NULL ||
	as->as_signeralgorithm == KEYNOTE_ALGORITHM_NONE)
    {
	keynote_errno = ERROR_SYNTAX;
	return NULL;
    }

    alg = keynote_get_sig_algorithm(sigalg, &hashtype, &encoding,
				    &internalenc);
    if (((alg != as->as_signeralgorithm) &&
	 !((alg == KEYNOTE_ALGORITHM_RSA) &&
	   (as->as_signeralgorithm == KEYNOTE_ALGORITHM_X509)) &&
	 !((alg == KEYNOTE_ALGORITHM_X509) &&
	   (as->as_signeralgorithm == KEYNOTE_ALGORITHM_RSA))) ||
        ((alg != keyalg) &&
	 !((alg == KEYNOTE_ALGORITHM_RSA) &&
	   (keyalg == KEYNOTE_ALGORITHM_X509)) &&
	 !((alg == KEYNOTE_ALGORITHM_X509) &&
	   (keyalg == KEYNOTE_ALGORITHM_RSA))))
    {
	keynote_errno = ERROR_SYNTAX;
	return NULL;
    }

    sig = strchr(sigalg, ':');
    if (sig == NULL)
    {
	keynote_errno = ERROR_SYNTAX;
	return NULL;
    }

    sig++;

    switch (hashtype)
    {
	case KEYNOTE_HASH_SHA1:
    	    hashlen = 20;
	    memset(res2, 0, hashlen);
	    SHA1_Init(&shscontext);
	    SHA1_Update(&shscontext, as->as_startofsignature,
			as->as_allbutsignature - as->as_startofsignature);
	    SHA1_Update(&shscontext, sigalg, (char *) sig - sigalg);
	    SHA1_Final(res2, &shscontext);
	    break;
   
	case KEYNOTE_HASH_MD5:
	    hashlen = 16;
	    memset(res2, 0, hashlen);
	    MD5_Init(&md5context);
	    MD5_Update(&md5context, as->as_startofsignature,
		       as->as_allbutsignature - as->as_startofsignature);
	    MD5_Update(&md5context, sigalg, (char *) sig - sigalg);
	    MD5_Final(res2, &md5context);
	    break;

	case KEYNOTE_HASH_NONE:
	    break;
    }

    if ((alg == KEYNOTE_ALGORITHM_DSA) &&
	(hashtype == KEYNOTE_HASH_SHA1) &&
	(internalenc == INTERNAL_ENC_ASN1) &&
	((encoding == ENCODING_HEX) || (encoding == ENCODING_BASE64)))
    {
	dsa = (DSA *) key;
	sbuf = calloc(DSA_size(dsa), sizeof(unsigned char));
	if (sbuf == NULL)
	{
	    keynote_errno = ERROR_MEMORY;
	    return NULL;
	}

	if (DSA_sign(0, res2, hashlen, sbuf, &slen, dsa) <= 0)
	{
	    free(sbuf);
	    keynote_errno = ERROR_SYNTAX;
	    return NULL;
	}
    }
    else
      if ((alg == KEYNOTE_ALGORITHM_RSA) &&
          ((hashtype == KEYNOTE_HASH_SHA1) ||
           (hashtype == KEYNOTE_HASH_MD5)) &&
          (internalenc == INTERNAL_ENC_PKCS1) &&
          ((encoding == ENCODING_HEX) || (encoding == ENCODING_BASE64)))
      {
          rsa = (RSA *) key;
          sbuf = calloc(RSA_size(rsa), sizeof(unsigned char));
          if (sbuf == NULL)
          {
              keynote_errno = ERROR_MEMORY;
              return NULL;
          }

          if (RSA_sign_ASN1_OCTET_STRING(RSA_PKCS1_PADDING, res2, hashlen,
					 sbuf, &slen, rsa) <= 0)
          {
              free(sbuf);
              keynote_errno = ERROR_SYNTAX;
              return NULL;
          }
      }
    else
      if ((alg == KEYNOTE_ALGORITHM_X509) &&
	  (hashtype == KEYNOTE_HASH_SHA1) &&
	  (internalenc == INTERNAL_ENC_ASN1))
      {
	  if ((biokey = BIO_new(BIO_s_mem())) == NULL)
	  {
	      keynote_errno = ERROR_SYNTAX;
	      return NULL;
	  }
	  
	  if (BIO_write(biokey, key, strlen(key) + 1) <= 0)
	  {
	      BIO_free(biokey);
	      keynote_errno = ERROR_SYNTAX;
	      return NULL;
	  }

	  /* RSA-specific */
	  rsa = (RSA *) PEM_read_bio_RSAPrivateKey(biokey, NULL, NULL, NULL);
	  if (rsa == NULL)
	  {
	      BIO_free(biokey);
	      keynote_errno = ERROR_SYNTAX;
	      return NULL;
	  }

	  sbuf = calloc(RSA_size(rsa), sizeof(char));
	  if (sbuf == NULL)
	  {
	      BIO_free(biokey);
	      RSA_free(rsa);
	      keynote_errno = ERROR_MEMORY;
	      return NULL;
	  }

	  if (RSA_sign(NID_shaWithRSAEncryption, res2, hashlen, sbuf, &slen,
		       rsa) <= 0)
          {
	      BIO_free(biokey);
	      RSA_free(rsa);
	      free(sbuf);
	      keynote_errno = ERROR_SIGN_FAILURE;
	      return NULL;
	  }

	  BIO_free(biokey);
	  RSA_free(rsa);
      }
      else /* Other algorithms here */
      {
	  keynote_errno = ERROR_SYNTAX;
	  return NULL;
      }

    /* ASCII encoding */
    switch (encoding)
    {
	case ENCODING_HEX:
	    i = kn_encode_hex(sbuf, (char **) &finalbuf, slen);
	    free(sbuf);
	    if (i != 0)
	      return NULL;
	    break;

	case ENCODING_BASE64:
	    finalbuf = calloc(2 * slen, sizeof(unsigned char));
	    if (finalbuf == NULL)
	    {
		keynote_errno = ERROR_MEMORY;
		free(sbuf);
		return NULL;
	    }

	    if ((slen = kn_encode_base64(sbuf, slen, finalbuf, 
					 2 * slen)) == -1)
	    {
		free(sbuf);
		return NULL;
	    }
	    break;

	default:
	    free(sbuf);
	    keynote_errno = ERROR_SYNTAX;
	    return NULL;
    }

    /* Replace as->as_signature */
    len = strlen(sigalg) + strlen(finalbuf) + 1;
    as->as_signature = calloc(len, sizeof(char));
    if (as->as_signature == NULL)
    {
	free(finalbuf);
	keynote_errno = ERROR_MEMORY;
	return NULL;
    }

    /* Concatenate algorithm name and signature value */
    snprintf(as->as_signature, len, "%s%s", sigalg, finalbuf);
    free(finalbuf);
    finalbuf = as->as_signature;

    /* Verify the newly-created signature if requested */
    if (verifyflag)
    {
	/* Do the signature verification */
	if (keynote_sigverify_assertion(as) != SIGRESULT_TRUE)
	{
	    as->as_signature = NULL;
	    free(finalbuf);
	    if (keynote_errno == 0)
	      keynote_errno = ERROR_SYNTAX;
	    return NULL;
	}

	as->as_signature = NULL;
    }
    else
      as->as_signature = NULL;

    /* Everything ok */
    return (char *) finalbuf;
}
예제 #3
0
/*
 * Recurse on graph discovery.
 */
static int
rec_evaluate_query(struct assertion *as)
{
    struct assertion *ast;
    struct keylist *kl;
    int i, s;

    as->as_kresult = KRESULT_IN_PROGRESS;

    /*
     * If we get the minimum result or an error from evaluating this
     * assertion, we don't need to recurse.
     */
    keynote_evaluate_assertion(as);
    if (keynote_errno != 0)
    {
        as->as_kresult = KRESULT_DONE;
        if (keynote_errno)
            as->as_error = keynote_errno;
        if (keynote_errno == ERROR_MEMORY)
            return -1;
        else
        {
            keynote_errno = 0;  /* Ignore syntax errors for now */
            return 0;
        }
    }

    if (as->as_result == 0)
    {
        as->as_kresult = KRESULT_DONE;
        return as->as_result;
    }

    for (kl = as->as_keylist;
            kl != (struct keylist *) NULL;
            kl = kl->key_next)
    {
        switch (keynote_in_action_authorizers(kl->key_key, kl->key_alg))
        {
        case -1:
            as->as_kresult = KRESULT_DONE;
            if (keynote_errno == ERROR_MEMORY)
            {
                as->as_error = ERROR_MEMORY;
                return -1;
            }
            else
            {
                keynote_errno = 0; /* Reset */
                continue;
            }

        case RESULT_FALSE:    /* Not there, check for assertions instead */
            break;

        case RESULT_TRUE:     /* Ok, don't bother with assertions */
            keynote_current_assertion = (struct assertion *) NULL;
            continue;
        }

        for (i = 0;; i++)
        {
            ast = keynote_find_assertion(kl->key_key, i, kl->key_alg);
            if (ast == (struct assertion *) NULL)
                break;

            if (ast->as_kresult == KRESULT_IN_PROGRESS) /* Cycle detected */
                continue;

            if (ast->as_kresult == KRESULT_UNTOUCHED)   /* Recurse if needed */
                rec_evaluate_query(ast);

            /* Check for errors */
            if (keynote_errno == ERROR_MEMORY)
            {
                as->as_error = ERROR_MEMORY;
                as->as_kresult = KRESULT_DONE;
                return -1;
            }
            else
                keynote_errno = 0; /* Reset */
        }
    }

    keynote_current_assertion = as;
    s = keynote_parse_keypred(as, 0);
    keynote_current_assertion = (struct assertion *) NULL;

    if (keynote_errno == ERROR_MEMORY)
    {
        as->as_error = ERROR_MEMORY;
        as->as_kresult = KRESULT_DONE;
        return -1;
    }
    else if (keynote_errno)
    {
        keynote_errno = 0;
        s = 0;
    }

    /* Keep lower of two */
    as->as_result = (as->as_result < s ? as->as_result : s);

    /* Check the signature now if we haven't done so already */
    if (as->as_sigresult == SIGRESULT_UNTOUCHED)
    {
        if (!(as->as_flags & ASSERT_FLAG_LOCAL))
            as->as_sigresult = keynote_sigverify_assertion(as);
        else
            as->as_sigresult = SIGRESULT_TRUE;    /* Trusted assertion */
    }

    if (as->as_sigresult != SIGRESULT_TRUE)
    {
        as->as_result = 0;
        as->as_sigresult = SIGRESULT_FALSE;
        if (keynote_errno != ERROR_MEMORY)
            keynote_errno = 0; /* Reset */
        else
        {
            as->as_error = ERROR_MEMORY;
            as->as_kresult = KRESULT_DONE;
            return -1;
        }
    }

    as->as_kresult = KRESULT_DONE;
    return as->as_result;
}