Factor out rhizome_hex_to_bytes() and chartonybl()

This commit is contained in:
Andrew Bettison 2012-06-25 14:50:38 +09:30
parent 05d8ac5d05
commit 208b9c15fd
9 changed files with 141 additions and 146 deletions

View File

@ -18,10 +18,45 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "serval.h"
#include "rhizome.h"
#include <ctype.h>
char hexdigit[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
static inline int _is_xsubstring(const char *text, int len)
{
while (len--)
if (!isxdigit(*text++))
return 0;
return 1;
}
static inline int _is_xstring(const char *text, int len)
{
while (len--)
if (!isxdigit(*text++))
return 0;
return *text == '\0';
}
/* Return true iff 'len' bytes starting at 'text' are hex digits, upper or lower case.
Does not check the following byte.
@author Andrew Bettison <andrew@servalproject.com>
*/
int is_xsubstring(const char *text, int len)
{
return _is_xsubstring(text, len);
}
/* Return true iff the nul-terminated string 'text' has length 'len' and consists only of hex
digits, upper or lower case.
@author Andrew Bettison <andrew@servalproject.com>
*/
int is_xstring(const char *text, int len)
{
return _is_xstring(text, len);
}
char *tohex(char *dstHex, const unsigned char *srcBinary, size_t bytes)
{
char *p;
@ -51,6 +86,46 @@ int fromhexstr(unsigned char *dstBinary, const char *srcHex, size_t bytes)
return (fromhex(dstBinary, srcHex, bytes) == bytes && srcHex[bytes * 2] == '\0') ? 0 : -1;
}
int rhizome_strn_is_manifest_id(const char *id)
{
return _is_xsubstring(id, RHIZOME_MANIFEST_ID_STRLEN);
}
int rhizome_str_is_manifest_id(const char *id)
{
return _is_xstring(id, RHIZOME_MANIFEST_ID_STRLEN);
}
int rhizome_strn_is_bundle_key(const char *key)
{
return _is_xsubstring(key, RHIZOME_BUNDLE_KEY_STRLEN);
}
int rhizome_str_is_bundle_key(const char *key)
{
return _is_xstring(key, RHIZOME_BUNDLE_KEY_STRLEN);
}
int rhizome_strn_is_bundle_crypt_key(const char *key)
{
return _is_xsubstring(key, RHIZOME_CRYPT_KEY_STRLEN);
}
int rhizome_str_is_bundle_crypt_key(const char *key)
{
return _is_xstring(key, RHIZOME_CRYPT_KEY_STRLEN);
}
int rhizome_strn_is_file_hash(const char *hash)
{
return _is_xsubstring(hash, RHIZOME_FILEHASH_STRLEN);
}
int rhizome_str_is_file_hash(const char *hash)
{
return _is_xstring(hash, RHIZOME_FILEHASH_STRLEN);
}
int extractDid(unsigned char *packet,int *ofs,char *did)
{
int d=0;
@ -173,7 +248,7 @@ char *str_toupper_inplace(char *str)
return str;
}
int hexvalue(unsigned char c)
int hexvalue(char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;

View File

@ -353,28 +353,6 @@ int rhizome_bundle_push_update(char *id,long long version,unsigned char *data,in
return WHY("Not implemented");
}
int chartonybl(int c)
{
if (c>='A'&&c<='F') return 0x0a+(c-'A');
if (c>='a'&&c<='f') return 0x0a+(c-'a');
if (c>='0'&&c<='9') return 0x00+(c-'0');
return 0;
}
int rhizome_hex_to_bytes(const char *in,unsigned char *out,int hexChars)
{
int i;
for(i=0;i<hexChars;i++)
{
int byte=i>>1;
int nybl=chartonybl(in[i]);
out[byte]=out[byte]<<4;
out[byte]|=nybl;
}
return 0;
}
/* When voice traffic is being carried, we need to throttle Rhizome down
to a more sensible level. Or possibly even supress it entirely.
*/

View File

@ -240,7 +240,6 @@ int rhizome_manifest_finalise(rhizome_manifest *m);
int rhizome_add_manifest(rhizome_manifest *m_in,int ttl);
void rhizome_bytes_to_hex_upper(unsigned const char *in, char *out, int byteCount);
int rhizome_hex_to_bytes(const char *in,unsigned char *out,int hexChars);
int rhizome_find_privatekey(rhizome_manifest *m);
rhizome_signature *rhizome_sign_hash(rhizome_manifest *m, const unsigned char *authorSid);
int rhizome_server_free_http_request(rhizome_http_request *r);
@ -259,7 +258,6 @@ int rhizome_server_http_response_header(rhizome_http_request *r,int result,
char *mime_type,unsigned long long bytes);
int rhizome_server_sql_query_fill_buffer(int rn,rhizome_http_request *r);
double rhizome_manifest_get_double(rhizome_manifest *m,char *var,double default_value);
int chartonybl(int c);
int rhizome_manifest_extract_signature(rhizome_manifest *m,int *ofs);
int rhizome_update_file_priority(const char *fileid);
int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,

View File

@ -47,35 +47,31 @@ int rhizome_manifest_verify(rhizome_manifest *m)
/* Make sure that id variable is correct */
{
char *id=rhizome_manifest_get(m,"id",NULL,0);
if (!id) {
unsigned char manifest_id[RHIZOME_MANIFEST_ID_BYTES];
char *id = rhizome_manifest_get(m,"id",NULL,0);
if (!id) {
WARN("Manifest lacks 'id' field");
m->errors++;
}
else {
unsigned char manifest_bytes[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
rhizome_hex_to_bytes(id,manifest_bytes,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
if ((m->sig_count==0)||
memcmp(&m->signatories[0][0],manifest_bytes,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES))
{
if (debug&DEBUG_RHIZOME) {
if (m->sig_count>0) {
DEBUGF("Manifest id variable does not match first signature block (signature key is %s)",
/* XXX bit of a hack that relies on SIDs and signing public keys being the same length */
overlay_render_sid(&m->signatories[0][0])
);
} else {
DEBUG("Manifest has no signature blocks, but should have self-signature block");
}
}
m->errors++;
m->selfSigned=0;
} else m->selfSigned=1;
} else if (fromhexstr(manifest_id, id, RHIZOME_MANIFEST_ID_BYTES) == -1) {
WARN("Invalid manifest 'id' field");
m->errors++;
} else if (m->sig_count == 0 || memcmp(m->signatories[0], manifest_id, RHIZOME_MANIFEST_ID_BYTES) != 0) {
if (debug&DEBUG_RHIZOME) {
if (m->sig_count>0) {
DEBUGF("Manifest id variable does not match first signature block (signature key is %s)",
alloca_tohex(m->signatories[0], crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES)
);
} else {
DEBUG("Manifest has no signature blocks, but should have self-signature block");
}
}
m->errors++;
m->selfSigned=0;
} else {
m->selfSigned=1;
}
}
/* Mark as finalised, as it is all read and intact,
unless of course it has errors, or is lacking a self-signature. */
if (!m->errors) m->finalised=1;
@ -146,25 +142,26 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu
DEBUGF("read manifest line: %s=%s", var, catv(value, buf, sizeof buf));
}
*/
m->vars[m->var_count]=strdup(var);
m->values[m->var_count]=strdup(value);
if (!strcasecmp(var,"ID"))
{
/* Parse hex string of ID into public key */
rhizome_hex_to_bytes(value,m->cryptoSignPublic,
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
}
if ((!strcasecmp(var,"ID"))||(!strcasecmp(var,"FILEHASH"))) {
/* Also force to upper case to avoid case sensitive comparison problems later. */
int i;
for(i=0;i<strlen(m->vars[m->var_count]);i++)
m->values[m->var_count][i]=toupper(m->values[m->var_count][i]);
m->vars[m->var_count] = strdup(var);
m->values[m->var_count] = strdup(value);
if (strcasecmp(var,"id") == 0) {
str_toupper_inplace(m->values[m->var_count]);
/* Parse hex string of ID into public key, and force to upper case. */
if (fromhexstr(m->cryptoSignPublic, value, RHIZOME_MANIFEST_ID_BYTES) == -1) {
WARNF("Invalid manifest id: %s", value);
m->errors++;
}
} else if (strcasecmp(var,"filehash") == 0 || strcasecmp(var,"BK") == 0) {
/* Force to upper case to avoid case sensitive comparison problems later. */
str_toupper_inplace(m->values[m->var_count]);
}
m->var_count++;
}
} else {
char buf[80];
if (0) WARNF("Skipping malformed line in manifest file %s: %s", bufferP ? "<buffer>" : filename, catv(line, buf, sizeof buf));
if (debug & DEBUG_RHIZOME) {
char buf[80];
DEBUGF("Skipping malformed line in manifest file %s: %s", bufferP ? "<buffer>" : filename, catv(line, buf, sizeof buf));
}
}
}
/* The null byte gets included in the check sum */
@ -180,21 +177,6 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu
return 0;
}
int rhizome_strn_is_file_hash(const char *text)
{
int i;
for (i = 0; i != RHIZOME_FILEHASH_STRLEN; ++i)
if (!isxdigit(text[i]))
return 0;
return 1;
}
int rhizome_str_is_file_hash(const char *text)
{
size_t len = strlen(text);
return len == RHIZOME_FILEHASH_STRLEN && rhizome_strn_is_file_hash(text);
}
int rhizome_hash_file(rhizome_manifest *m,const char *filename,char *hash_out)
{
/* Gnarf! NaCl's crypto_hash() function needs the whole file passed in in one

View File

@ -30,52 +30,6 @@ unsigned char *rhizome_bundle_shared_secret(rhizome_manifest *m)
return NULL;
}
static inline int _is_xsubstring(const char *text, int len)
{
while (len--)
if (!isxdigit(*text++))
return 0;
return 1;
}
static inline int _is_xstring(const char *text, int len)
{
while (len--)
if (!isxdigit(*text++))
return 0;
return *text == '\0';
}
int rhizome_strn_is_manifest_id(const char *id)
{
return _is_xsubstring(id, RHIZOME_MANIFEST_ID_STRLEN);
}
int rhizome_str_is_manifest_id(const char *id)
{
return _is_xstring(id, RHIZOME_MANIFEST_ID_STRLEN);
}
int rhizome_strn_is_bundle_key(const char *key)
{
return _is_xsubstring(key, RHIZOME_BUNDLE_KEY_STRLEN);
}
int rhizome_str_is_bundle_key(const char *key)
{
return _is_xstring(key, RHIZOME_BUNDLE_KEY_STRLEN);
}
int rhizome_strn_is_bundle_crypt_key(const char *key)
{
return _is_xsubstring(key, RHIZOME_CRYPT_KEY_STRLEN);
}
int rhizome_str_is_bundle_crypt_key(const char *key)
{
return _is_xstring(key, RHIZOME_CRYPT_KEY_STRLEN);
}
int rhizome_manifest_createid(rhizome_manifest *m)
{
m->haveSecret=1;
@ -109,11 +63,12 @@ int rhizome_find_keypair_bytes(unsigned char *p,unsigned char *s) {
if ( sqlite3_step(statement) == SQLITE_ROW ) {
if (sqlite3_column_type(statement,0)==SQLITE_TEXT) {
const unsigned char *hex=sqlite3_column_text(statement,0);
rhizome_hex_to_bytes((char *)hex,s,
crypto_sign_edwards25519sha512batch_SECRETKEYBYTES*2);
/* XXX TODO Decrypt secret using a keyring password */
sqlite3_finalize(statement);
return 0;
if (fromhexstr(s, (const char *)hex, crypto_sign_edwards25519sha512batch_SECRETKEYBYTES) != -1) {
/* XXX TODO Decrypt secret using a keyring password */
return 0;
}
return WHY("Database contains invalid secret key");
}
}
sqlite3_finalize(statement);

View File

@ -1034,7 +1034,10 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
}
const char *q_manifestid = (const char *) sqlite3_column_text(statement, 0);
size_t manifestidsize = sqlite3_column_bytes(statement, 0); // must call after sqlite3_column_text()
if (manifestidsize != crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES * 2) {
unsigned char manifest_id[RHIZOME_MANIFEST_ID_BYTES];
if ( manifestidsize != crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES * 2
|| fromhexstr(manifest_id, q_manifestid, RHIZOME_MANIFEST_ID_BYTES) == -1
) {
ret = WHYF("Malformed manifest.id from query: %s", q_manifestid);
break;
}
@ -1106,7 +1109,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
}
}
if (ret == 1) {
rhizome_hex_to_bytes(q_manifestid, blob_m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
memcpy(blob_m->cryptoSignPublic, manifest_id, RHIZOME_MANIFEST_ID_BYTES);
memcpy(blob_m->fileHexHash, m->fileHexHash, RHIZOME_FILEHASH_STRLEN + 1);
blob_m->fileHashedP = 1;
blob_m->fileLength = m->fileLength;
@ -1135,6 +1138,9 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
*/
int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
{
unsigned char manifest_id[RHIZOME_MANIFEST_ID_BYTES];
if (fromhexstr(manifest_id, manifestid, RHIZOME_MANIFEST_ID_BYTES) == -1)
return WHY("Invalid manifest ID");
char sqlcmd[1024];
int n = snprintf(sqlcmd, sizeof(sqlcmd), "SELECT id, manifest, version, inserttime FROM manifests WHERE id = ?");
if (n >= sizeof(sqlcmd))
@ -1148,9 +1154,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
ret = WHY(sqlite3_errmsg(rhizome_db));
} else {
char manifestIdUpper[RHIZOME_MANIFEST_ID_STRLEN + 1];
strncpy(manifestIdUpper, manifestid, sizeof manifestIdUpper);
manifestIdUpper[RHIZOME_MANIFEST_ID_STRLEN] = '\0';
str_toupper_inplace(manifestIdUpper);
tohex(manifestIdUpper, manifest_id, RHIZOME_MANIFEST_ID_BYTES);
sqlite3_bind_text(statement, 1, manifestIdUpper, -1, SQLITE_STATIC);
while (sqlite3_step(statement) == SQLITE_ROW) {
if (!( sqlite3_column_count(statement) == 4
@ -1158,7 +1162,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
&& sqlite3_column_type(statement, 3) == SQLITE_INTEGER
)) {
)) {
ret = WHY("Incorrect statement column");
break;
}
@ -1175,7 +1179,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
ret = WHY("Invalid manifest blob from database");
} else {
ret = 1;
rhizome_hex_to_bytes(manifestid, m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
memcpy(m->cryptoSignPublic, manifest_id, RHIZOME_MANIFEST_ID_BYTES);
const char *blob_service = rhizome_manifest_get(m, "service", NULL, 0);
if (blob_service == NULL)
ret = WHY("Manifest is missing 'service' field");

View File

@ -113,7 +113,7 @@ int rhizome_manifest_version_cache_store(rhizome_manifest *m)
/* Work out bin number in cache */
for(i=0;i<RHIZOME_VERSION_CACHE_NYBLS;i++)
{
int nybl=chartonybl(id[i]);
int nybl=hexvalue(id[i]);
bin=(bin<<4)|nybl;
}
bin=bin>>RHIZOME_VERSION_CACHE_SHIFT;
@ -126,7 +126,7 @@ int rhizome_manifest_version_cache_store(rhizome_manifest *m)
entry->version=manifest_version;
for(i=0;i<24;i++)
{
int byte=(chartonybl(id[(i*2)])<<4)|chartonybl(id[(i*2)+1]);
int byte=(hexvalue(id[(i*2)])<<4)|hexvalue(id[(i*2)+1]);
entry->idprefix[i]=byte;
}
@ -157,7 +157,7 @@ int rhizome_manifest_version_cache_lookup(rhizome_manifest *m)
/* Work out bin number in cache */
for(i=0;i<RHIZOME_VERSION_CACHE_NYBLS;i++)
{
int nybl=chartonybl(id[i]);
int nybl=hexvalue(id[i]);
bin=(bin<<4)|nybl;
}
bin=bin>>RHIZOME_VERSION_CACHE_SHIFT;
@ -169,8 +169,8 @@ int rhizome_manifest_version_cache_lookup(rhizome_manifest *m)
for(i=0;i<24;i++)
{
int byte=
(chartonybl(id[(i*2)])<<4)
|chartonybl(id[(i*2)+1]);
(hexvalue(id[(i*2)])<<4)
|hexvalue(id[(i*2)+1]);
if (byte!=entry->idprefix[i]) break;
}
if (i==24) {
@ -247,7 +247,7 @@ int rhizome_manifest_version_cache_lookup(rhizome_manifest *m)
entry->version=stored_version;
for(i=0;i<24;i++)
{
int byte=(chartonybl(id[(i*2)])<<4)|chartonybl(id[(i*2)+1]);
int byte=(hexvalue(id[(i*2)])<<4)|hexvalue(id[(i*2)+1]);
entry->idprefix[i]=byte;
}
/* Finally, say that it isn't worth RXing this manifest */

View File

@ -448,7 +448,7 @@ int rhizome_server_sql_query_fill_buffer(int rn,rhizome_http_request *r)
for(i=0;i<r->source_record_size;i++)
/* convert the two nybls and make a byte */
r->buffer[r->buffer_length+i]
=(chartonybl(value[i<<1])<<4)|chartonybl(value[(i<<1)+1]);
=(hexvalue(value[i<<1])<<4)|hexvalue(value[(i<<1)+1]);
} else
/* direct binary value */
bcopy(value,&r->buffer[r->buffer_length],r->source_record_size);

View File

@ -409,9 +409,14 @@ int confParseBoolean(const char *text, const char *option_name);
int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
struct sockaddr *recvaddr,unsigned int *recvaddrlen);
int is_xsubstring(const char *text, int len);
int is_xstring(const char *text, int len);
char *tohex(char *dstHex, const unsigned char *srcBinary, size_t bytes);
size_t fromhex(unsigned char *dstBinary, const char *srcHex, size_t bytes);
int fromhexstr(unsigned char *dstBinary, const char *srcHex, size_t bytes);
int hexvalue(char c);
char *str_toupper_inplace(char *s);
int validateSid(const char *sid);
int stowSid(unsigned char *packet, int ofs, const char *sid);
int stowDid(unsigned char *packet,int *ofs,char *did);
@ -436,8 +441,6 @@ void serverCleanUp();
int isTransactionInCache(unsigned char *transaction_id);
void insertTransactionInCache(unsigned char *transaction_id);
int hexvalue(unsigned char c);
char *str_toupper_inplace(char *s);
int packetOk(int interface,unsigned char *packet,int len,
unsigned char *transaction_id, int recvttl,
struct sockaddr *recvaddr,int recvaddrlen,int parseP);