It turns out that the current Serpent CBC-MAC transform takes the raw
DH shared secret, and parcels it up in byte ranges for the various
uses (some of which are published). Well, obviously this is not a
good idea.
But also it means the interface isn't set up to allow the size of the
key data provided to the transform to be determined by the size of the
DH modulus.
Fix this latter interface problem. Now a transform can set its keylen
to 0, meaning it will be provided with the whole of the DH private
value.
We don't use this new feature yet. We can't make the existing
transform use it without breaking compatibility, but it will be used
by the new EAX-based transform.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
+ st->ops.ceil_len=(mpz_sizeinbase(&st->p,2)+7)/8;
+ /* According to the docs, mpz_sizeinbase(,256) is allowed to return
+ * an answer which is 1 too large. But mpz_sizeinbase(,2) isn't. */
+
return new_closure(&st->cl);
}
return new_closure(&st->cl);
}
void *st;
int32_t max_start_pad; /* these three are all <<< INT_MAX */
int32_t max_end_pad;
void *st;
int32_t max_start_pad; /* these three are all <<< INT_MAX */
int32_t max_end_pad;
+ int32_t keylen; /* 0 means give the transform exactly as much as there is */
transform_createinstance_fn *create;
};
transform_createinstance_fn *create;
};
struct dh_if {
void *st;
int32_t len; /* Approximate size of modulus in bytes */
struct dh_if {
void *st;
int32_t len; /* Approximate size of modulus in bytes */
+ int32_t ceil_len; /* Number of bytes just sufficient to contain modulus */
dh_makepublic_fn *makepublic;
dh_makeshared_fn *makeshared;
};
dh_makepublic_fn *makepublic;
dh_makeshared_fn *makeshared;
};
uint64_t timeout; /* Timeout for current state */
uint8_t *dhsecret;
uint8_t *sharedsecret;
uint64_t timeout; /* Timeout for current state */
uint8_t *dhsecret;
uint8_t *sharedsecret;
+ uint32_t sharedsecretlen;
struct transform_inst_if *new_transform; /* For key setup/verify */
};
struct transform_inst_if *new_transform; /* For key setup/verify */
};
/* Generate the shared key */
st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,m.pk,
/* Generate the shared key */
st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,m.pk,
- st->sharedsecret,st->transform->keylen);
+ st->sharedsecret,st->sharedsecretlen);
/* Set up the transform */
st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
/* Set up the transform */
st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
- st->transform->keylen);
m.pk[m.pklen]=0;
/* Generate the shared key */
st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,m.pk,
m.pk[m.pklen]=0;
/* Generate the shared key */
st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,m.pk,
- st->sharedsecret,st->transform->keylen);
+ st->sharedsecret,st->sharedsecretlen);
/* Set up the transform */
st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
/* Set up the transform */
st->new_transform->setkey(st->new_transform->st,st->sharedsecret,
- st->transform->keylen);
memset(st->remoteN,0,NONCELEN);
st->new_transform->delkey(st->new_transform->st);
memset(st->dhsecret,0,st->dh->len);
memset(st->remoteN,0,NONCELEN);
st->new_transform->delkey(st->new_transform->st);
memset(st->dhsecret,0,st->dh->len);
- memset(st->sharedsecret,0,st->transform->keylen);
+ memset(st->sharedsecret,0,st->sharedsecretlen);
transport_peers_clear(st,&st->setup_peers);
/* XXX mlock these */
st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret");
transport_peers_clear(st,&st->setup_peers);
/* XXX mlock these */
st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret");
- st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret");
+ st->sharedsecretlen=st->transform->keylen?:st->dh->ceil_len;
+ st->sharedsecret=safe_malloc(st->sharedsecretlen,"site:sharedsecret");
/* We need to compute some properties of our comms */
#define COMPUTE_WORST(pad) \
/* We need to compute some properties of our comms */
#define COMPUTE_WORST(pad) \