// Duplicates a bytestring bytestring *bytestring_dup(const bytestring *bs) { bytestring *dup = bytestring_new(bs->length); bytestring_set_bytes(dup, bs->data, bs->length); return dup; }
cardreader_t* cardreader_new(const char *card_reader_name) { cardreader_t* reader = (cardreader_t *)malloc(sizeof(cardreader_t)); memset(reader,0,sizeof(cardreader_t)); if (card_reader_name==NULL || strcmp(card_reader_name,"none")==0) { reader->name=strdup("(none)"); if (null_initialize(reader)==0) return NULL; } else if (strncmp(card_reader_name,"pcsc://",7)==0) { reader->name=strdup(card_reader_name); if (pcsc_initialize(reader)==0) return NULL; } else if (strncmp(card_reader_name,"replay://",9)==0) { reader->name=strdup(card_reader_name); if (replay_initialize(reader)==0) return NULL; } else { free(reader); log_printf(LOG_ERROR,"Unknown reader type : %s",card_reader_name); return NULL; } reader->atr=bytestring_new(8); reader->cardlog=cardreplay_new(); return reader; }
bytestring *bytestring_new_from_string(const char *str) { size_t len = strlen(str); bytestring *bs = bytestring_new(len); bytestring_set_bytes(bs, (const uint8_t *)str, len); return bs; }
crypto_error_t crypto_mac(bytestring_t *dst, const bytestring_t *ctx, const bytestring_t *src) { unsigned u,v; unsigned char tmp[8]; unsigned char clr[8]; unsigned char alg; crypto_error_t retval; bytestring_t *padded_src; DES_key_schedule key_schedule; DES_key_schedule key_schedule2; bytestring_get_element(&alg,ctx,0); if (alg==CRYPTO_ALG_ISO9797_M3) { padded_src = bytestring_new(8); retval = crypto_pad(padded_src,ctx,src); if (retval!=CRYPTO_OK) { bytestring_free(padded_src); return retval; } memset(tmp,0,8); memcpy(&key_schedule,ctx->data+KS_HEADER_SIZE,DES_KS_SIZE); memcpy(&key_schedule2,ctx->data+KS_HEADER_SIZE+DES_KS_SIZE,DES_KS_SIZE); for (u=0; u<bytestring_get_size(padded_src)/8; u++) { for (v=0; v<8; v++) clr[v]=padded_src->data[u*8+v]^tmp[v]; DES_ecb_encrypt((const_DES_cblock *)clr, (DES_cblock *)tmp, &key_schedule, DES_ENCRYPT); } memcpy(clr,tmp,8); DES_ecb_encrypt((const_DES_cblock *)clr, (DES_cblock *)tmp, &key_schedule2, DES_DECRYPT); memcpy(clr,tmp,8); DES_ecb_encrypt((const_DES_cblock *)clr, (DES_cblock *)tmp, &key_schedule, DES_ENCRYPT); bytestring_assign_data(dst,8,tmp); bytestring_free(padded_src); } else return CRYPTO_ERROR_UNKNOWN_ALGORITHM; return CRYPTO_OK; }
// Parses a frame's command. Returns true iff progress was made. bool frameparser_parse_command(frameparser *fp, buffer *b) { log_printf(LOG_LEVEL_DEBUG, "frameparser_parse_command\n"); // Valid input in this state is a string followed by CR/LF or LF, which matches a known frame command // Try to find LF line terminator int lfpos = buffer_find_byte(b, '\x0A'); if (lfpos < 0) // No LF yet? { if (buffer_get_length(b) > LIMIT_FRAME_CMD_LINE_LEN) frameparser_set_error(fp, "Line length limit exceeded waiting for command"); return false; // No progress } else if (lfpos == 0) abort(); // Should never happen in this state // Figure out number of bytes in command string int len = lfpos; if (buffer_get_byte(b, len - 1) == '\x0D') len--; // Extract the command into a new bytestring bytestring *bs = bytestring_new(len); buffer_append_bytestring(b, bs, 0, len); bytestring_dump(bs); // Consume the current line buffer_consume(b, lfpos + 1); // Find the command code for this command frame_command cmd = frame_command_code(bytestring_get_bytes(bs), bytestring_get_length(bs)); // Clean up the bytestring bytestring_free(bs); // Make sure command is valid if (cmd == CMD_NONE) { frameparser_set_error(fp, "Unknown command"); return false; } // Set up a new frame structure to hold parsed data if (!fp->cur_frame) fp->cur_frame = frame_new(); // Store parsed data frame_set_command(fp->cur_frame, cmd); // Got a valid command, so headers should be next fp->state = FP_STATE_HEADER; return true; }
int main() { bytestring_t *key = bytestring_new_from_string("0123456789ABCDEFh"); bytestring_t *ctx = bytestring_new(8); bytestring_t *src = bytestring_new_from_string("5468652071756663h"); bytestring_t *dst = bytestring_new(8); bytestring_t *clr = bytestring_new(8); if (crypto_create_key(ctx,0,key)==CRYPTO_OK) { fprintf(stderr,"Create key succeeded\n"); } else { fprintf(stderr,"Create key failed\n"); return -3; } if (crypto_encrypt(dst,ctx,src,NULL)==CRYPTO_OK) { fprintf(stderr,"Crypto: %s\n",bytestring_to_alloc_string(dst)); } else fprintf(stderr,"Crypto failed\n"); if (crypto_decrypt(clr,ctx,dst,NULL)==CRYPTO_OK) { if (bytestring_is_equal(clr,src)) fprintf(stderr,"Decrypted clear text matches initial text\n"); else fprintf(stderr,"Crypto: %s\n",bytestring_to_alloc_string(clr)); } else fprintf(stderr,"Crypto failed\n"); return 0; }
// Record an error void frameparser_set_error(frameparser *fp, char *fmt, ...) { fp->state = FP_STATE_ERROR; // Bail out if there is already an error. We only want to record the first one. if (fp->error) return; va_list args; va_start(args, fmt); fp->error = bytestring_append_vprintf(bytestring_new(0), fmt, args); va_end(args); return; }
crypto_error_t crypto_encrypt(bytestring_t *dst, const bytestring_t *ctx, const bytestring_t *src, const bytestring_t *iv) { unsigned pad_type; bytestring_t *padded_src; crypto_error_t retval; bytestring_get_element((unsigned char *)&pad_type,ctx,1); if (pad_type==0 && (bytestring_get_size(src)&0x7)==0) return crypto_cipher(dst,ctx,src,iv,DES_ENCRYPT); padded_src=bytestring_new(8); retval = crypto_pad(padded_src,ctx,src); if (retval==CRYPTO_OK) { retval = crypto_cipher(dst,ctx,padded_src,iv,DES_ENCRYPT); } bytestring_free(padded_src); return retval; }
bytestring_t* bytestring_new_from_hex(const char *hex) { bytestring_t *dat=bytestring_new(); unsigned hex_len=strlen(hex); unsigned c; size_t i=0; bytestring_reserve(dat,hex_len/2); while (i<hex_len) { if (is_blank(hex[i])) { i++; continue; } c=(hex_nibble(hex[i])<<4) | hex_nibble(hex[i+1]); if (c>255) return dat; bytestring_pushback(dat,(unsigned char)c); i+=2; } return dat; }
/* static void update_dump(update_t *update, FILE* out) { update_item_t *item = update->items; fprintf(out,"Update version %s\n",update->update_version); while (item) { update_item_dump(item,out); item = item->next; } } */ static int update_load(update_t *update, const char *data, unsigned data_len) { char *ptr = (char *)data; unsigned ptr_len = data_len; char *data_end; char *value; update_item_t *item = NULL; bytestring_t *signature; bytestring_t *source; int signature_verified; #define fail_update(m) { log_printf(LOG_ERROR,"Failed to parse update information: %s",m); \ goto update_new_fail; } if ((value = tokenizer_get_record(&ptr,&ptr_len))==NULL) fail_update("Missing header"); if (strcmp(value,"header")!=0) fail_update("Incorrect header"); g_free(value); if ((value = tokenizer_get_field("version",&ptr,&ptr_len))==NULL) fail_update("missing version"); update->update_version = value; /* don't free value */ data_end = ptr; while ((value = tokenizer_get_record(&ptr,&ptr_len))!=NULL) { if (strcmp(value,"update")!=0) break; g_free(value); item = update_item_new(); if ((value = tokenizer_get_field("file",&ptr,&ptr_len))==NULL) fail_update("missing file name"); item->file = value; if ((value = tokenizer_get_field("url",&ptr,&ptr_len))==NULL) fail_update("missing url"); item->url = value; if ((value = tokenizer_get_field("required_version",&ptr,&ptr_len))==NULL) fail_update("missing required version"); item->required_version = value; if ((value = tokenizer_get_field("digest",&ptr,&ptr_len))==NULL) fail_update("missing digest"); bytestring_assign_digit_string(&item->digest,value); g_free(value); if (bytestring_get_size(&item->digest)!=SHA256_DIGEST_LENGTH) fail_update("incorrect digest length"); if ((value = tokenizer_get_field("message",&ptr,&ptr_len))==NULL) fail_update("missing message"); item->message = value; update->item_count++; item->next = update->items; update->items = item; item = NULL; data_end = ptr; } if (value==NULL) fail_update("missing section"); if (strcmp(value,"authentication")!=0) fail_update("missing authentication"); g_free(value); if ((value = tokenizer_get_field("signature",&ptr,&ptr_len))==NULL) fail_update("missing signature"); signature = bytestring_new(8); bytestring_assign_digit_string(signature,value); g_free(value); log_printf(LOG_DEBUG,"Verifying %d bit signature on update information (%d bytes), representing %d files.", bytestring_get_size(signature)*8,data_end-data,update->item_count); source = bytestring_new(8); bytestring_assign_data(source,data_end-data,(const unsigned char *)data); if (verify_signature(source,signature)==0) { log_printf(LOG_ERROR,"Signature verification failed on update information."); signature_verified = 0; update_clear(update); } else { log_printf(LOG_INFO,"Signature verification succeeded on update information."); signature_verified = 1; } bytestring_free(signature); bytestring_free(source); return signature_verified; update_new_fail: if (value) g_free(value); if (update) update_clear(update); if (item) update_item_free(item); return 0; }
bytestring_t* bytestring_duplicate(const bytestring_t *bs) { bytestring_t* res=bytestring_new(); bytestring_assign_data(res,bs->len,bs->data); return res; }
// Unescapes a bytestring according to the rules used for headers: // "\r" => CR, "\n" => LF, "\c" => ":", "\\" => "\" // If the input bytestring is well-formed, it is consumed and a new bytestring // is returned. If the input bytestring is malformed, it is not consumed and // NULL is returned. static bytestring *unescape_header_bytestring(bytestring *in) { bytestring *out = NULL; bool success = true; size_t inlen = bytestring_get_length(in); int pos = 0; // Handle trivial case of zero-length input if (inlen == 0) return in; while (pos < inlen) { // Find next backslash int bspos = bytestring_find_byte(in, '\\', pos); if (bspos == -1) { // No backslash, can take the rest of the input verbatim if (!out) return in; // No transforms needed, so just return the input string // Create output string, if needed if (!out) out = bytestring_new(bytestring_get_length(in)); // Grab rest of input string size_t count = inlen - pos; bytestring_append_bytestring(out, in, pos, count); pos += count; } else { // There was a backslash, so we'll need to do some transforming // Create output string, if needed if (!out) out = bytestring_new(bytestring_get_length(in)); // Grab all characters before the backslash, if any if (bspos > 0) { // Copy everything before the backslash size_t count = bspos - pos; bytestring_append_bytestring(out, in, pos, count); pos += count; } // Process the character following the backslash if (bytestring_get_length(in) == (bspos + 1)) { success = false; // There is no following character break; } else { uint8_t c = bytestring_get_bytes(in)[bspos + 1]; if (c == '\\') bytestring_append_byte(out, '\\'); else if (c == 'r') bytestring_append_byte(out, '\x0D'); // CR else if (c == 'n') bytestring_append_byte(out, '\x0A'); // LF else if (c == 'c') bytestring_append_byte(out, ':'); else { success = false; // Invalid escape sequence break; } pos += 2; } } } // Handle errors if (!success) { if (out) bytestring_free(out); return NULL; } // All done bytestring_free(in); return out; }
// Parses a header line. Returns true iff progress was made. bool frameparser_parse_header(frameparser *fp, buffer *b) { log_printf(LOG_LEVEL_DEBUG, "frameparser_parse_header\n"); // Valid input in this state is either: // 1. CR/LF or LF alone, denoting the end of headers // 2. A key name, followed by a colon, followed by a value name, terminated with CR/LF or LF // Try to find LF line terminator int lfpos = buffer_find_byte(b, '\x0A'); if (lfpos < 0) // No LF yet? { if (buffer_get_length(b) > LIMIT_FRAME_HEADER_LINE_LEN) frameparser_set_error(fp, "Line length limit exceeded waiting for header"); return false; // No progress } else if (lfpos == 0) // LF alone { buffer_consume(b, 1); frameparser_parse_headers_complete(fp); return true; } else if ((lfpos == 1) && (buffer_get_byte(b, 0) == '\x0D')) // CR/LF alone { buffer_consume(b, 2); frameparser_parse_headers_complete(fp); return true; } // Figure out number of bytes in the line int len = lfpos; if (buffer_get_byte(b, len - 1) == '\x0D') len--; // Find the colon delimiter int colonpos = buffer_find_byte_within(b, ':', 0, len); if (colonpos < 0) // No colon? { frameparser_set_error(fp, "Expected colon delimiter on header line"); return false; } else if (colonpos == 0) // Starts with colon? { frameparser_set_error(fp, "Header name has zero length"); return false; } // Extract the key bytestring *key = bytestring_new(colonpos); buffer_append_bytestring(b, key, 0, colonpos); // Extract the value bytestring *val = bytestring_new(len - colonpos - 1); buffer_append_bytestring(b, val, colonpos + 1, len - colonpos - 1); // Consume the current line buffer_consume(b, lfpos + 1); // Unescape the key and value if needed frame_command cmd = frame_get_command(fp->cur_frame); if ((cmd != CMD_CONNECT) && (cmd != CMD_CONNECTED)) { key = unescape_header_bytestring(key); val = unescape_header_bytestring(val); } bytestring_dump(key); bytestring_dump(val); headerbundle *hb = frame_get_headerbundle(fp->cur_frame); headerbundle_append_header(hb, key, val); // The bundle takes ownership of key and val return true; }