int bytestring_erase(bytestring_t *bs, unsigned pos, unsigned len) { if (pos>=bs->len) return BYTESTRING_OK; if (pos+len>=bs->len) return bytestring_resize(bs,pos); memmove(bs->data+pos,bs->data+pos+len,bs->len-pos-len); bytestring_resize(bs,bs->len-len); return BYTESTRING_OK; }
int bytestring_assign_uchar(bytestring_t* bs, unsigned len, unsigned char c) { bytestring_resize(bs,len); memset(bs->data,c,len); return BYTESTRING_OK; }
int bytestring_assign_data(bytestring_t* bs, unsigned len, const unsigned char *data) { bytestring_resize(bs,len); memcpy(bs->data,data,len); return BYTESTRING_OK; }
// Append printf()-style string data to the end of a bytestring. bytestring *bytestring_append_printf(bytestring *bs, const char *fmt, ...) { va_list args; while (1) { int count; int slack = bs->size - bs->length; // Attempt the printf() with whatever slack space we have left va_start(args, fmt); count = vsnprintf((char *) bs->data + bs->length, slack, fmt, args); va_end(args); // Unexpected failure if (count < 0) abort(); // If there was enough space, we're all done if (count < slack) { bs->length += count; return bs; } // Add the required amount of slack space bytestring_resize(bs, bs->length + count + 1); // +1 because we need space for NUL byte not included in count } }
int bytestring_insert_uchar(bytestring_t *bs, unsigned pos, unsigned len, unsigned char c) { if (pos>=bs->len) return bytestring_append_uchar(bs,len,c); bytestring_resize(bs,bs->len+len); memmove(bs->data+pos+len,bs->data+pos,len); memset(bs->data,c,len); return BYTESTRING_OK; }
int bytestring_insert_data(bytestring_t *bs, unsigned pos, unsigned len, const unsigned char* data) { if (pos>=bs->len) return bytestring_append_data(bs,len,data); bytestring_resize(bs,bs->len+len); memmove(bs->data+pos+len,bs->data+pos,len); memcpy(bs->data,data,len); return BYTESTRING_OK; }
// Append a single byte to the end of the bytestring. bytestring *bytestring_append_byte(bytestring *bs, uint8_t byte) { // Ensure enough space to hold all data if (bs->size < (bs->length + 1)) bytestring_resize(bs, (bs->length + 1)); // Append the data to the end bs->data[bs->length] = byte; bs->length++; return bs; }
// Append the given bytes to the end of the bytestring. bytestring *bytestring_append_bytes(bytestring *bs, const uint8_t *data, size_t length) { // Ensure enough space to hold all data if (bs->size < (bs->length + length)) bytestring_resize(bs, (bs->length + length)); // Append the data to the end memcpy(bs->data + bs->length, data, length); bs->length += length; return bs; }
// Replace the contents of the bytestring with the given bytes. bytestring *bytestring_set_bytes(bytestring *bs, const uint8_t *data, size_t length) { // Ensure enough space to hold all data if (bs->size < length) bytestring_resize(bs, length); // Copy the data memcpy(bs->data, data, length); bs->length = length; return bs; }
crypto_error_t crypto_digest(bytestring_t *dst, const bytestring_t *ctx, const bytestring_t *src) { unsigned char alg; bytestring_get_element(&alg,ctx,0); if (alg==CRYPTO_ALG_SHA1) { bytestring_resize(dst,SHA_DIGEST_LENGTH); SHA1(src->data,bytestring_get_size(src),dst->data); } else return CRYPTO_ERROR_UNKNOWN_ALGORITHM; return CRYPTO_OK; }
// Append data to one bytestring from another, using the given source position and length. bytestring *bytestring_append_bytestring(bytestring *bs, const bytestring *src, int position, size_t length) { // Start position bounds check if ((position < 0) || (position >= src->length)) return bs; // Nothing to do // Length bounds check if (position + length > src->length) length = src->length - position; // Ensure enough space to hold all data if (bs->size < (bs->length + length)) bytestring_resize(bs, (bs->length + length)); // Append the data to the end memcpy(bs->data + bs->length, src->data + position, length); bs->length += length; return bs; }
// As above, but don't use varargs. bytestring *bytestring_append_vprintf(bytestring *bs, const char *fmt, va_list args) { int count; int slack = bs->size - bs->length; // Make a copy of the original args, in case we need to retry va_list original_args; va_copy(original_args, args); // Attempt the printf() with whatever slack space we have left count = vsnprintf((char *) bs->data + bs->length, slack, fmt, args); // Unexpected failure if (count < 0) abort(); // If there was enough space, we're all done if (count < slack) { va_end(original_args); bs->length += count; return bs; } // Add the required amount of slack space bytestring_resize(bs, bs->length + count + 1); // +1 because we need space for NUL byte not included in count slack = bs->size - bs->length; // Retry the printf() count = vsnprintf((char *) bs->data + bs->length, slack, fmt, original_args); va_end(original_args); // This should not happen, since we allocated enough space if ((count < 0) || (count >= slack)) abort(); // Fix up length bs->length += count; return bs; }
static crypto_error_t crypto_cipher(bytestring_t *dst, const bytestring_t *ctx, const bytestring_t *src, const bytestring_t *iv, int enc) { unsigned u; unsigned char alg; DES_key_schedule key_schedule; DES_key_schedule key_schedule2; if (bytestring_get_element(&alg,ctx,0)!=BYTESTRING_OK) return CRYPTO_ERROR_UNKNOWN; if ((bytestring_get_size(src)&0x7)!=0) return CRYPTO_ERROR_BAD_CLEARTEXT_LENGTH; switch (alg) { case CRYPTO_ALG_DES_ECB: bytestring_resize(dst,bytestring_get_size(src)); memcpy(&key_schedule,ctx->data+KS_HEADER_SIZE,DES_KS_SIZE); for (u=0; u<bytestring_get_size(src)/8; u++) DES_ecb_encrypt((const_DES_cblock *)(src->data+u*8), (DES_cblock *)(dst->data+u*8), &key_schedule, enc); break; case CRYPTO_ALG_DES_CBC: if (iv==NULL || bytestring_get_size(iv)!=8) return CRYPTO_ERROR_BAD_IV_LENGTH; bytestring_resize(dst,bytestring_get_size(src)); memcpy(&key_schedule,ctx->data+KS_HEADER_SIZE,DES_KS_SIZE); DES_ncbc_encrypt(src->data, dst->data, bytestring_get_size(src), &key_schedule, (DES_cblock *)(iv->data), enc); break; case CRYPTO_ALG_DES2_EDE_ECB: bytestring_resize(dst,bytestring_get_size(src)); 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(src)/8; u++) DES_ecb2_encrypt((const_DES_cblock *)(src->data+u*8), (DES_cblock *)(dst->data+u*8), &key_schedule, &key_schedule2, enc); break; case CRYPTO_ALG_DES2_EDE_CBC: if (iv==NULL || bytestring_get_size(iv)!=8) return CRYPTO_ERROR_BAD_IV_LENGTH; bytestring_resize(dst,bytestring_get_size(src)); 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); DES_ede2_cbc_encrypt(src->data, dst->data, bytestring_get_size(src), &key_schedule, &key_schedule2, (DES_cblock *)(iv->data), enc); break; default: return CRYPTO_ERROR_UNKNOWN_ALGORITHM; } return CRYPTO_OK; }