/**
 * crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
 * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
 * bytes from ${inbuf}, writing the result into ${outbuf}.  If the buffers
 * ${inbuf} and ${outbuf} overlap, they must be identical.
 */
void
crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf,
    uint8_t * outbuf, size_t buflen)
{
	uint8_t pblk[16];
	size_t pos;
	int bytemod;

	for (pos = 0; pos < buflen; pos++) {
		/* How far through the buffer are we? */
		bytemod = stream->bytectr % 16;

		/* Generate a block of cipherstream if needed. */
		if (bytemod == 0) {
			be64enc(pblk, stream->nonce);
			be64enc(pblk + 8, stream->bytectr / 16);
			AES_encrypt(pblk, stream->buf, stream->key);
		}

		/* Encrypt a byte. */
		outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod];

		/* Move to the next byte of cipherstream. */
		stream->bytectr += 1;
	}
}
Пример #2
0
/**
 * proto_lbs_response_params2(Q, ID, blklen, blkno, lastblk):
 * Send a PARAMS2 response with ID ${ID} to the write queue ${Q} indicating
 * that the block size is ${blklen} bytes, the next available block # is
 * ${blkno}, and the last block written was ${lastblk}.
 */
int
proto_lbs_response_params2(struct netbuf_write * Q, uint64_t ID,
    uint32_t blklen, uint64_t blkno, uint64_t lastblk)
{
	uint8_t * wbuf;

	/* Get a packet data buffer. */
	if ((wbuf = wire_writepacket_getbuf(Q, ID, 20)) == NULL)
		goto err0;

	/* Write the packet data. */
	be32enc(&wbuf[0], blklen);
	be64enc(&wbuf[4], blkno);
	be64enc(&wbuf[12], lastblk);

	/* Finish the packet. */
	if (wire_writepacket_done(Q, wbuf, 20))
		goto err0;

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
Пример #3
0
static int test_be64enc() {
  uint8_t buf[8];
  be64enc(buf, 0x0102030405060708ULL);
  if(buf[0] != 1 || buf[1] != 2 || buf[2] != 3 || buf[3] != 4 ||
     buf[4] != 5 || buf[5] != 6 || buf[6] != 7 || buf[7] != 8)
    return -1;

  be64enc(buf, 0xffefdfcfbfaf9f8fULL);
  if(buf[0] != 0xff || buf[1] != 0xef || buf[2] != 0xdf || buf[3] != 0xcf ||
     buf[4] != 0xbf || buf[5] != 0xaf || buf[6] != 0x9f || buf[7] != 0x8f)
    return -1;

  return 0;
}
Пример #4
0
static const char *tencode(int t, uint64_t val)
{
	static char res[64];
	uint8_t buf[16];
	bool be = t > 0;
	int i;

	if (t < 0) t = -t;

	memset(buf, 0xFC, sizeof(buf));

	if (be) {
		switch (t) {
		case 2: be16enc(buf, val); break;
		case 4: be32enc(buf, val); break;
		case 8: be64enc(buf, val); break;
		}
	} else {
		switch (t) {
		case 2: le16enc(buf, val); break;
		case 4: le32enc(buf, val); break;
		case 8: le64enc(buf, val); break;
		}
	}

	for (i = t; i < (int)sizeof(buf); i++) {
		if (buf[i] != 0xFC)
			return "OVER";
	}

	snprintf(res, sizeof(res), "%02X %02X %02X %02X %02X %02X %02X %02X ",
		 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
	res[t*3 - 1] = 0;
	return res;
}
Пример #5
0
/**
 * proto_lbs_response_append(Q, ID, status, blkno):
 * Send an APPEND response with ID ${ID} to the write queue ${Q} with status
 * code ${status} and next block number ${blkno} if ${status} is zero.
 */
int
proto_lbs_response_append(struct netbuf_write * Q, uint64_t ID,
    uint32_t status, uint64_t blkno)
{
	uint8_t * wbuf;
	size_t len;

	/* Compute the response length. */
	len = (status == 0) ? 12 : 4;

	/* Get a packet data buffer. */
	if ((wbuf = wire_writepacket_getbuf(Q, ID, len)) == NULL)
		goto err0;

	/* Write the packet data. */
	be32enc(&wbuf[0], status);
	if (status == 0)
		be64enc(&wbuf[4], blkno);

	/* Finish the packet. */
	if (wire_writepacket_done(Q, wbuf, len))
		goto err0;

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
Пример #6
0
/**
 * proto_crypt_enc(ibuf, len, obuf, k):
 * Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in
 * ${k}, and write the result into ${obuf}.
 */
void
proto_crypt_enc(uint8_t * ibuf, size_t len, uint8_t obuf[PCRYPT_ESZ],
    struct proto_keys * k)
{
	HMAC_SHA256_CTX ctx;
	uint8_t pnum_exp[8];

	/* Sanity-check the length. */
	assert(len <= PCRYPT_MAXDSZ);

	/* Copy the decrypted data into the encrypted buffer. */
	memcpy(obuf, ibuf, len);

	/* Pad up to PCRYPT_MAXDSZ with zeroes. */
	memset(&obuf[len], 0, PCRYPT_MAXDSZ - len);

	/* Add the length. */
	be32enc(&obuf[PCRYPT_MAXDSZ], len);

	/* Encrypt the buffer in-place. */
	crypto_aesctr_buf(k->k_aes, k->pnum, obuf, obuf, PCRYPT_MAXDSZ + 4);

	/* Append an HMAC. */
	be64enc(pnum_exp, k->pnum);
	HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
	HMAC_SHA256_Update(&ctx, obuf, PCRYPT_MAXDSZ + 4);
	HMAC_SHA256_Update(&ctx, pnum_exp, 8);
	HMAC_SHA256_Final(&obuf[PCRYPT_MAXDSZ + 4], &ctx);

	/* Increment packet number. */
	k->pnum += 1;
}
Пример #7
0
void write_kdfp(uint8_t *addr, kdfp *kdfp) {
    uint64_t *N  = (uint64_t *) (addr + SALT_LEN);
    uint32_t *r  = (uint32_t *) (N + 1);
    uint32_t *p  = (uint32_t *) (r + 1);
    memcpy(addr, kdfp->salt, SALT_LEN);
    be64enc(N, kdfp->N);
    be32enc(r, kdfp->r);
    be32enc(p, kdfp->p);
}
Пример #8
0
/**
 * mkval(X, Y, buf):
 * Write the 40-byte value
 * offset  length
 * ------  ------
 *    0       8    64-bit big-endian X * 2^16 + Y
 *    8      32    sha256(\001.(64-bit big-endian X).(64-bit big-endian Y))
 * into ${buf}.
 */
void
mkval(uint64_t X, uint64_t Y, uint8_t * buf)
{
	SHA256_CTX ctx;
	uint8_t hbuf[17];

	/* Store big-endian X * 2^16 + Y. */
	be64enc(&buf[0], (X << 16) + Y);

	/* Generate \001.X.Y. */
	hbuf[0] = 0;
	be64enc(&hbuf[1], X);
	be64enc(&hbuf[9], Y);

	/* Compute sha256(\001.X.Y). */
	SHA256_Init(&ctx);
	SHA256_Update(&ctx, hbuf, 17);
	SHA256_Final(&buf[8], &ctx);
}
Пример #9
0
static void
vhd_make_footer(struct vhd_footer *footer, uint64_t image_size,
    uint32_t disk_type, uint64_t data_offset)
{
	uuid_t id;

	memset(footer, 0, sizeof(*footer));
	be64enc(&footer->cookie, VHD_FOOTER_COOKIE);
	be32enc(&footer->features, VHD_FEATURES_RESERVED);
	be32enc(&footer->version, VHD_VERSION);
	be64enc(&footer->data_offset, data_offset);
	be32enc(&footer->timestamp, vhd_timestamp());
	be32enc(&footer->creator_tool, VHD_CREATOR_TOOL);
	be32enc(&footer->creator_version, VHD_CREATOR_VERSION);
	be32enc(&footer->creator_os, VHD_CREATOR_OS);
	be64enc(&footer->original_size, image_size);
	be64enc(&footer->current_size, image_size);
	vhd_geometry(footer, image_size);
	be32enc(&footer->disk_type, disk_type);
	mkimg_uuid(&id);
	vhd_uuid_enc(&footer->id, &id);
	be32enc(&footer->checksum, vhd_checksum(footer, sizeof(*footer)));
}
Пример #10
0
/**
 * crypto_session_sign(CS, buf, buflen, sig):
 * Generate sig = write_auth(buf).
 */
void
crypto_session_sign(CRYPTO_SESSION * CS, const uint8_t * buf, size_t buflen,
    uint8_t sig[32])
{
	uint8_t nonce[8];

	/* Convert nonce to 8-byte big-endian format, and increment. */
	be64enc(nonce, CS->auth_write_nonce);
	CS->auth_write_nonce += 1;

	/* Generate hash. */
	crypto_hash_data_key_2(CS->auth_write, 32,
	    nonce, 8, buf, buflen, sig);
}
Пример #11
0
static bool stratum_notify_m7(struct stratum_ctx *sctx, json_t *params)
{
    const char *job_id, *prevblock, *accroot, *merkleroot, *version, *ntime;
    int height;
    bool clean;

    job_id = json_string_value(json_array_get(params, 0));
    prevblock = json_string_value(json_array_get(params, 1));
    accroot = json_string_value(json_array_get(params, 2));
    merkleroot = json_string_value(json_array_get(params, 3));
    height = json_integer_value(json_array_get(params, 4));
    version = json_string_value(json_array_get(params, 5));
    ntime = json_string_value(json_array_get(params, 6));
    clean = json_is_true(json_array_get(params, 7));

    if (!job_id || !prevblock || !accroot || !merkleroot ||
            !version || !height || !ntime ||
            strlen(prevblock) != 32*2 ||
            strlen(accroot) != 32*2 ||
            strlen(merkleroot) != 32*2 ||
            strlen(ntime) != 8*2 || strlen(version) != 2*2) {
        applog(LOG_ERR, "Stratum (M7) notify: invalid parameters");
        return false;
    }

    pthread_mutex_lock(&sctx->work_lock);

    if (!sctx->job.job_id || strcmp(sctx->job.job_id, job_id)) {
        sctx->job.xnonce2 = (unsigned char *)realloc(sctx->job.xnonce2, sctx->xnonce2_size);
        memset(sctx->job.xnonce2, 0, sctx->xnonce2_size);
    }
    free(sctx->job.job_id);
    sctx->job.job_id = strdup(job_id);

    hex2bin(sctx->job.m7prevblock, prevblock, 32);
    hex2bin(sctx->job.m7accroot, accroot, 32);
    hex2bin(sctx->job.m7merkleroot, merkleroot, 32);
    be64enc(sctx->job.m7height, height);
    hex2bin(sctx->job.m7version, version, 2);
    hex2bin(sctx->job.m7ntime, ntime, 8);
    sctx->job.clean = clean;

    sctx->job.diff = sctx->next_diff;

    pthread_mutex_unlock(&sctx->work_lock);

    return true;
}
Пример #12
0
static void
le_lebuffer_copyfromdesc(struct lance_softc *sc, void *tov, int off, int len)
{
	struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc;
	caddr_t to = tov;

	for (; len >= 8; len -= 8, off += 8, to += 8)
		be64enc(to,
		    bus_read_8(lesc->sc_bres, off));
	for (; len >= 4; len -= 4, off += 4, to += 4)
		be32enc(to,
		    bus_read_4(lesc->sc_bres, off));
	for (; len >= 2; len -= 2, off += 2, to += 2)
		be16enc(to,
		    bus_read_2(lesc->sc_bres, off));
	if (len == 1)
		*to = bus_read_1(lesc->sc_bres, off);
}
Пример #13
0
/**
 * crypto_session_verify(CS, buf, buflen, sig):
 * Verify that sig = read_auth(buf).  Return non-zero if the signature
 * does not match.
 */
int
crypto_session_verify(CRYPTO_SESSION * CS, const uint8_t * buf, size_t buflen,
    const uint8_t sig[32])
{
	uint8_t nonce[8];
	uint8_t sig_actual[32];

	/* Convert nonce to 8-byte big-endian format, and increment. */
	be64enc(nonce, CS->auth_read_nonce);
	CS->auth_read_nonce += 1;

	/* Generate hash. */
	crypto_hash_data_key_2(CS->auth_read, 32,
	    nonce, 8, buf, buflen, sig_actual);

	/* Determine if the signatures match. */
	if (crypto_verify_bytes(sig, sig_actual, 32))
		return (1);
	else
		return (0);
}
Пример #14
0
/**
 * proto_crypt_dec(ibuf, obuf, k):
 * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}.  If the data
 * is valid, write it into ${obuf} and return the length; otherwise, return
 * -1.
 */
ssize_t proto_crypt_dec(uint8_t ibuf[PCRYPT_ESZ], uint8_t * obuf,
    struct proto_keys * k)
{
	HMAC_SHA256_CTX ctx;
	uint8_t hbuf[32];
	uint8_t pnum_exp[8];
	size_t len;

	/* Verify HMAC. */
	be64enc(pnum_exp, k->pnum);
	HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
	HMAC_SHA256_Update(&ctx, ibuf, PCRYPT_MAXDSZ + 4);
	HMAC_SHA256_Update(&ctx, pnum_exp, 8);
	HMAC_SHA256_Final(hbuf, &ctx);
	if (crypto_verify_bytes(hbuf, &ibuf[PCRYPT_MAXDSZ + 4], 32))
		return (-1);

	/* Decrypt the buffer in-place. */
	crypto_aesctr_buf(k->k_aes, k->pnum, ibuf, ibuf, PCRYPT_MAXDSZ + 4);

	/* Increment packet number. */
	k->pnum += 1;

	/* Parse length. */
	len = be32dec(&ibuf[PCRYPT_MAXDSZ]);

	/* Make sure nobody is being evil here... */
	if ((len == 0) || (len > PCRYPT_MAXDSZ))
		return (-1);

	/* Copy the bytes into the output buffer. */
	memcpy(obuf, ibuf, len);

	/* Return the decrypted length. */
	return (len);
}
Пример #15
0
static int
vhd_dyn_write(int fd)
{
	struct vhd_footer footer;
	struct vhd_dyn_header header;
	uint64_t imgsz;
	lba_t blk, blkcnt, nblks;
	uint32_t *bat;
	void *bitmap;
	size_t batsz;
	uint32_t sector;
	int bat_entries, error, entry;

	imgsz = image_get_size() * secsz;
	bat_entries = imgsz / VHD_BLOCK_SIZE;

	vhd_make_footer(&footer, imgsz, VHD_DISK_TYPE_DYNAMIC, sizeof(footer));
	if (sparse_write(fd, &footer, sizeof(footer)) < 0)
		return (errno);

	memset(&header, 0, sizeof(header));
	be64enc(&header.cookie, VHD_HEADER_COOKIE);
	be64enc(&header.data_offset, ~0ULL);
	be64enc(&header.table_offset, sizeof(footer) + sizeof(header));
	be32enc(&header.version, VHD_VERSION);
	be32enc(&header.max_entries, bat_entries);
	be32enc(&header.block_size, VHD_BLOCK_SIZE);
	be32enc(&header.checksum, vhd_checksum(&header, sizeof(header)));
	if (sparse_write(fd, &header, sizeof(header)) < 0)
		return (errno);

	batsz = bat_entries * sizeof(uint32_t);
	batsz = (batsz + VHD_SECTOR_SIZE - 1) & ~(VHD_SECTOR_SIZE - 1);
	bat = malloc(batsz);
	if (bat == NULL)
		return (errno);
	memset(bat, 0xff, batsz);
	blkcnt = VHD_BLOCK_SIZE / secsz;
	sector = (sizeof(footer) + sizeof(header) + batsz) / VHD_SECTOR_SIZE;
	for (entry = 0; entry < bat_entries; entry++) {
		blk = entry * blkcnt;
		if (image_data(blk, blkcnt)) {
			be32enc(&bat[entry], sector);
			sector += (VHD_BLOCK_SIZE / VHD_SECTOR_SIZE) + 1;
		}
	}
	if (sparse_write(fd, bat, batsz) < 0) {
		free(bat);
		return (errno);
	}
	free(bat);

	bitmap = malloc(VHD_SECTOR_SIZE);
	if (bitmap == NULL)
		return (errno);
	memset(bitmap, 0xff, VHD_SECTOR_SIZE);

	blk = 0;
	blkcnt = VHD_BLOCK_SIZE / secsz;
	error = 0;
	nblks = image_get_size();
	while (blk < nblks) {
		if (!image_data(blk, blkcnt)) {
			blk += blkcnt;
			continue;
		}
		if (sparse_write(fd, bitmap, VHD_SECTOR_SIZE) < 0) {
			error = errno;
			break;
		}
		error = image_copyout_region(fd, blk, blkcnt);
		if (error)
			break;
		blk += blkcnt;
	}
	free(bitmap);
	if (blk != nblks)
		return (error);

	if (sparse_write(fd, &footer, sizeof(footer)) < 0)
		return (errno);

	return (0);
}
Пример #16
0
/* Do a round of deletes if appropriate. */
static int
poke(struct deleteto * D)
{
	uint64_t BIT;
	uint64_t X;
	uint8_t DeletedMarker[8];

	/* If we're trying to shut down, don't do anything. */
	if (D->shuttingdown)
		return (0);

	/* If operations are already in progress, don't do anything. */
	if (! D->idle)
		return (0);

	/* Sanity-check. */
	assert(D->npending == 0);

	/*
	 * Store the M to object DeletedMarker if it's a multiple of 256
	 * (periodic stores so DeletedMarker doesn't fall too far behind
	 * reality if we are doing a very large number of deletes) and we
	 * haven't yet stored this value of M.
	 *
	 * If we crash and restart, we may end up re-issuing as many as ~256
	 * deletes;but  this is better than more-frequent updating of the
	 * deletion marker since (a) DELETEs are free but PUTs aren't, and
	 * (b) we want to optimize for the common case, which is a long-lived
	 * lbs-s3 process.
	 */
	if ((D->M % 256 == 0) && (D->updateDeletedTo == 1)) {
		D->idle = 0;
		D->npending += 1;
		be64enc(DeletedMarker, D->M);
		if (proto_s3_request_put(D->Q, D->bucket, "DeletedMarker",
		    8, DeletedMarker, callback_done, D))
			goto err0;
		D->updateDeletedTo = 0;
	}

	/* If we can't delete anything, don't. */
	if (D->N <= D->M)
		return (0);

	/*
	 * We want to run one step of the DeleteTo algorithm: Delete or
	 * overwrite objects which are needed by M but not by M+1, and
	 * increment M.  If nothing needs to be done, we'll repeat the
	 * process for the new (incremented) M.
	 */

	/* For each bit... */
	for (BIT = 1; BIT != 0; BIT += BIT) {
		/* If it's set in M but not in M+1... */
		if (((D->M & BIT) == BIT) &&
		    (((D->M + 1) & BIT) == 0)) {
			/* M - M % BIT is deletable... */
			X = D->M - (D->M % BIT);

			/* ... unless it's a power of two. */
			if (X == BIT)
				continue;

			/* Issue a delete. */
			D->idle = 0;
			D->npending += 1;
			if (proto_s3_request_delete(D->Q, D->bucket,
			    objmap(X), callback_done, D))
				goto err0;
		}
	}

	/*
	 * Powers of 2 will never be DELETEd, and multiples of 256 can't be
	 * deleted until at least 256 iterations later (since N = ...abcdefgh)
	 * needs the file ...00000000 to still exist), but we don't need the
	 * data for M any more; so issue an empty PUT for it if it falls into
	 * one of those two categories.
	 */
	if (((D->M & (D->M-1)) == 0) || ((D->M % 256) == 0)) {
		D->idle = 0;
		D->npending += 1;
		if (proto_s3_request_put(D->Q, D->bucket, objmap(D->M),
		    0, NULL, callback_done, D))
			goto err0;
	}

	/* We've issued all the deletes needed for this M. */
	D->M = D->M + 1;
	D->updateDeletedTo = 1;

	/* If we haven't found anything to do yet, poke ourselves again. */
	if (D->idle)
		return (poke(D));

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}