예제 #1
0
static int digest_tlsa_usage(EVP_MD_CTX * mdctx, TLS_TLSA *tlsa,
			             const char *usage)
{
    char  **dgst;
    int     ok = 1;

    for (digest_string(usage); tlsa; tlsa = tlsa->next) {
	digest_string(tlsa->mdalg);
	digest_tlsa_argv(tlsa, pkeys);
	digest_tlsa_argv(tlsa, certs);
    }
    return (ok);
}
예제 #2
0
파일: hash.c 프로젝트: rOpenSec/openssl
SEXP R_digest(SEXP x, SEXP algo){
  if(!isString(x))
    error("Argument 'x' must be a character vector.");
  if(!isString(algo))
    error("Argument 'algo' must be a character vector.");

  int len = length(x);
  SEXP out = PROTECT(allocVector(STRSXP, len));
  for (int i = 0; i < len; i++) {
    /* check for NA */
    if(STRING_ELT(x, i) == NA_STRING) {
      SET_STRING_ELT(out, i, NA_STRING);
      continue;
    }
    /* create hash */
    const char* str = CHAR(STRING_ELT(x, i));
    unsigned char md_value[EVP_MAX_MD_SIZE];
    unsigned int md_len = digest_string(str, CHAR(asChar(algo)), strlen(str), md_value);

    /* create character vector */
    char mdString[2*md_len+1];
    for (int i = 0; i < md_len; i++) {
      sprintf(&mdString[i*2], "%02x", (unsigned int) md_value[i]);
    }
    mdString[2*md_len] = '\0';
    SET_STRING_ELT(out, i, mkChar(mdString));
  }
  UNPROTECT(1);
  return out;
}
예제 #3
0
static bool file_read_chunk(unsigned char *chunk, const unsigned char *digest,
		void *db_info)
{
	struct db *db = db_info;
	unsigned char *db_chunk;
	bool status = false;

	flock(db->fd, LOCK_SH);

	db_chunk = lookup_chunk(db, digest);
	if (db_chunk) {
		if (IS_ERR(db_chunk)) {
			TRACE("digest=%s: %s\n",
					digest_string(digest), 
					strerror(PTR_ERR(db_chunk)));
		} else {
			status = true;
			memcpy(chunk, db_chunk, CHUNK_SIZE);
			unmap_chunk(db_chunk);
		}
	}
	flock(db->fd, LOCK_UN);

	return status;
}
예제 #4
0
static bool write_chunk_sqlite(const unsigned char *chunk,
		const unsigned char *digest, void *db_info_ptr)
{
	static const char sql[] =
		"INSERT OR IGNORE INTO chunk(hash, data) VALUES(?,?)";
	struct db_info *db_info = db_info_ptr;
	sqlite3_stmt *stmt;
	int err;

	lock_db(db_info);

	err = sqlite3_prepare(db_info->db, sql, -1, &stmt, 0);
	if (err != SQLITE_OK) {
		ERROR("sqlite3_prepare failed: %s\n",
				sqlite3_errmsg(db_info->db));
		unlock_db(db_info);
		return false;
	}

	sqlite3_bind_text(stmt, 1, digest_string(digest), -1, SQLITE_STATIC);
	sqlite3_bind_blob(stmt, 2, chunk, CHUNK_SIZE, SQLITE_STATIC);

	err = sqlite3_step(stmt);
	assert(err != SQLITE_ROW);

	if (sqlite3_finalize(stmt) != SQLITE_OK) {
		ERROR("sqlite3_finalize failed: %s\n",
				sqlite3_errmsg(db_info->db));
		unlock_db(db_info);
		return false;
	}

	unlock_db(db_info);
	return true;
}
예제 #5
0
static bool file_write_chunk(const unsigned char *chunk,
		const unsigned char *digest, void *db_info)
{
	struct db *db = db_info;
	unsigned char *db_chunk;
	bool status = false;
	int error;

	flock(db->fd, LOCK_EX);

	db_chunk = lookup_chunk(db, digest);
	if (db_chunk) {
		if (IS_ERR(db_chunk)) {
			TRACE("lookup_chunk(%s): %s\n", 
					digest_string(digest),
					strerror(PTR_ERR(db_chunk)));
		} else
			status = true;
		goto out;
	}

	/*
	 * When adding a new chunk, the file needs to be resized, otherwise
	 * any access to the chunk will cause a SIGBUS. 
	 */
	if (ftruncate(db->fd, ((off_t)db->next_nr + 1) * CHUNK_SIZE)) {
		TRACE("ftruncate(%u * CHUNK_SIZE): %s\n",
				db->next_nr + 1,
				strerror(errno));
		goto out;
	}

	db_chunk = __map_chunk(db, db->next_nr, 0);
	if (IS_ERR(db_chunk)) {
		TRACE("__map_chunk(%u): %s\n", db->next_nr,
				strerror(PTR_ERR(db_chunk)));
		goto out;
	}

	memcpy(db_chunk, chunk, CHUNK_SIZE);

	error = hash_insert(db, *(uint32_t *)digest, db->next_nr);
	if (error) {
		TRACE("hash_insert(0x%x, %u): %s\n", *(uint32_t *)digest,
				db->next_nr, strerror(-error));
		goto out;
	}

	status = true;
	db->next_nr ++;
out:
	unmap_chunk(db_chunk);
	flock(db->fd, LOCK_UN);
	return status;
}
예제 #6
0
파일: digest_C.c 프로젝트: cran/SoDA
void R_digest_C(
          char ** Txt, 
          int * Algo, 
          int * Length, 
          char ** Output) {
  static char *output, buf[41]; 
  output = digest_string(*Txt, *Algo, *Length, buf);
  if(output == NULL && error_message != NULL)
    *Txt = error_message;
  else
    *Output = output;
}
예제 #7
0
static bool read_chunk_sqlite(unsigned char *chunk, const unsigned char *digest,
		void *db_info_ptr)
{
	static const char sql[] = "SELECT data FROM chunk WHERE hash = ?";
	struct db_info *db_info = db_info_ptr;
	sqlite3_stmt *stmt;
	int err;
	bool status = false;

	lock_db(db_info);
	err = sqlite3_prepare(db_info->db, sql, -1, &stmt, 0);
	if (err != SQLITE_OK) {
		ERROR("sqlite3_prepare failed: %d\n",
				sqlite3_errmsg(db_info->db));
		unlock_db(db_info);
		return false;
	}

	TRACE("%s\n", digest_string(digest));

	sqlite3_bind_text(stmt, 1, digest_string(digest), -1, SQLITE_STATIC);

	err = sqlite3_step(stmt);
	if (err != SQLITE_ROW) {
		ERROR("sqlite3_step failed: %s\n",
				sqlite3_errmsg(db_info->db));
	} else if (sqlite3_column_bytes(stmt, 0) != CHUNK_SIZE) {
		ERROR("sqlite3 query returned %d bytes instead of %d.\n",
				sqlite3_column_bytes(stmt, 0), CHUNK_SIZE);
	} else {
		TRACE("sqlite3 query got chunk.\n");
		memcpy(chunk, sqlite3_column_blob(stmt, 0), CHUNK_SIZE);
		status = true;
	}

	sqlite3_finalize(stmt);
	unlock_db(db_info);

	return status;
}
예제 #8
0
파일: hash.c 프로젝트: rOpenSec/openssl
SEXP R_digest_raw(SEXP x, SEXP algo){
  /* Check inputs */
  if(TYPEOF(x) != RAWSXP)
    error("Argument 'x' must be a raw vector.");

  /* Convert the Raw vector to an unsigned char */
  unsigned char md_value[EVP_MAX_MD_SIZE];
  unsigned int md_len = digest_string((const char*) RAW(x), CHAR(asChar(algo)), length(x), md_value);

  /* create raw output vector */
  SEXP out = PROTECT(allocVector(RAWSXP, md_len));
  memcpy(RAW(out), md_value, md_len);
  UNPROTECT(1);
  return out;
}
예제 #9
0
파일: digest_C.c 프로젝트: cran/SoDA
SEXP R_digest(
	    SEXP Txt, 
	    SEXP Algo, 
	    SEXP Length) {
  char *txt = (char *)STRING_VALUE(Txt);
  int algo = INTEGER_VALUE(Algo);
  int  length = INTEGER_VALUE(Length);
  SEXP result = R_NilValue;
  static char *output, buf[41]; 
  output = digest_string(txt, algo, length, buf);
  if(output == NULL) {
    error("Error in C computations of digest: %s",
	  (error_message == NULL) ? "<unspecified error>" : error_message);
    return result;
  }
     
  PROTECT(result=allocVector(STRSXP, 1));
  SET_STRING_ELT(result, 0, mkChar(output));
  UNPROTECT(1);			

  return result;
}
예제 #10
0
char   *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask,
			            const char *ciphers)
{
    EVP_MD_CTX *mdctx;
    const EVP_MD *md;
    const char *mdalg;
    unsigned char md_buf[EVP_MAX_MD_SIZE];
    unsigned int md_len;
    int     ok = 1;
    int     i;
    long    sslversion;
    VSTRING *result;

    /*
     * Try to use sha256: our serverid choice should be strong enough to
     * resist 2nd-preimage attacks with a difficulty comparable to that of
     * DANE TLSA digests.  Failing that, we compute serverid digests with the
     * default digest, but DANE requires sha256 and sha512, so if we must
     * fall back to our default digest, DANE support won't be available.  We
     * panic if the fallback algorithm is not available, as it was verified
     * available in tls_client_init() and must not simply vanish.
     */
    if ((md = EVP_get_digestbyname(mdalg = "sha256")) == 0
	&& (md = EVP_get_digestbyname(mdalg = props->mdalg)) == 0)
	msg_panic("digest algorithm \"%s\" not found", mdalg);

    /* Salt the session lookup key with the OpenSSL runtime version. */
    sslversion = SSLeay();

    mdctx = EVP_MD_CTX_create();
    checkok(EVP_DigestInit_ex(mdctx, md, NULL));
    digest_string(props->helo ? props->helo : "");
    digest_object(&sslversion);
    digest_object(&protomask);
    digest_string(ciphers);

    /*
     * All we get from the session cache is a single bit telling us whether
     * the certificate is trusted or not, but we need to know whether the
     * trust is CA-based (in that case we must do name checks) or whether it
     * is a direct end-point match.  We mustn't confuse the two, so it is
     * best to process only TA trust in the verify callback and check the EE
     * trust after. This works since re-used sessions always have access to
     * the leaf certificate, while only the original session has the leaf and
     * the full trust chain.
     * 
     * Only the trust anchor matchlist is hashed into the session key. The end
     * entity certs are not used to determine whether a certificate is
     * trusted or not, rather these are rechecked against the leaf cert
     * outside the verification callback, each time a session is created or
     * reused.
     * 
     * Therefore, the security context of the session does not depend on the EE
     * matching data, which is checked separately each time.  So we exclude
     * the EE part of the DANE structure from the serverid digest.
     * 
     * If the security level is "dane", we send SNI information to the peer.
     * This may cause it to respond with a non-default certificate.  Since
     * certificates for sessions with no or different SNI data may not match,
     * we must include the SNI name in the session id.
     */
    if (props->dane) {
	int     mixed = (props->dane->flags & TLS_DANE_FLAG_MIXED);

	digest_object(&mixed);
	digest_dane(props->dane, ta);
#if 0
	digest_dane(props->dane, ee);		/* See above */
#endif
	digest_string(props->tls_level == TLS_LEV_DANE ? props->host : "");
    }
    checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
    EVP_MD_CTX_destroy(mdctx);
    if (!ok)
	msg_fatal("error computing %s message digest", mdalg);

    /* Check for OpenSSL contract violation */
    if (md_len > EVP_MAX_MD_SIZE)
	msg_panic("unexpectedly large %s digest size: %u", mdalg, md_len);

    /*
     * Append the digest to the serverid.  We don't compare this digest to
     * any user-specified fingerprints.  Therefore, we don't need to use a
     * colon-separated format, which saves space in the TLS session cache and
     * makes logging of session cache lookup keys more readable.
     * 
     * This does however duplicate a few lines of code from the digest encoder
     * for colon-separated cert and pkey fingerprints. If that is a
     * compelling reason to consolidate, we could use that and append the
     * result.
     */
    result = vstring_alloc(strlen(props->serverid) + 1 + 2 * md_len);
    vstring_strcpy(result, props->serverid);
    VSTRING_ADDCH(result, '&');
    for (i = 0; i < md_len; i++) {
	VSTRING_ADDCH(result, hexcodes[(md_buf[i] & 0xf0) >> 4U]);
	VSTRING_ADDCH(result, hexcodes[(md_buf[i] & 0x0f)]);
    }
    VSTRING_TERMINATE(result);
    return (vstring_export(result));
}