Commit 82687cb8 authored by Jurre van Bergen's avatar Jurre van Bergen
Browse files

stab at removing otrv1 support

parent d8bc5628
Pipeline #52 failed with stages
in 1 minute and 59 seconds
stages:
- build
- test
- valgrindtest
- scanbuild
build_gcc:
image: offtherecord/libotr-gcc
stage: build
script:
- autoreconf --install
- ./configure
- make
- make install
build_clang:
image: offtherecord/libotr-clang
stage: build
script:
- export CC=/usr/bin/clang
- autoreconf --install
- ./configure
- make
- make install
test_list_gcc:
image: offtherecord/libotr-gcc
stage: test
script:
- autoreconf --install
- ./configure
- make
- make install
- cd tests
- make
- ./run.sh ./test_list
test_list_clang:
image: offtherecord/libotr-clang
stage: test
script:
- export CC=/usr/bin/clang
- autoreconf --install
- ./configure
- make
- make install
- cd tests
- make
- ./run.sh ./test_list
test_valgrind_gcc:
image: offtherecord/libotr-gcc
stage: valgrindtest
script:
- autoreconf --install
- ./configure
- make
- make install
- cd tests
- make
- valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./run.sh ./test_list
test_valgrind_clang:
image: offtherecord/libotr-clang
stage: valgrindtest
script:
- export CC=/usr/bin/clang
- autoreconf --install
- ./configure
- make
- make install
- cd tests
- make
- valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./run.sh ./test_list
scan_build:
image: offtherecord/libotr-clang
stage: scanbuild
script:
- autoreconf --install
- scan-build-8 ./configure
- mkdir /tmp/scan-build/
- scan-build-8 -o /tmp/scan-build/ make -j2
- tar cvf scanbuild.tar /tmp/scan-build/*
artifacts:
paths:
- scanbuild.tar
expire_in: 1 month
......@@ -48,8 +48,6 @@ void otrl_auth_dump(FILE *f, const OtrlAuthInfo *auth)
auth->authstate == OTRL_AUTHSTATE_AWAITING_REVEALSIG ?
"AWAITING_REVEALSIG" :
auth->authstate == OTRL_AUTHSTATE_AWAITING_SIG ? "AWAITING_SIG" :
auth->authstate == OTRL_AUTHSTATE_V1_SETUP ? "V1_SETUP" :
"INVALID");
fprintf(f, " Context: %p\n", auth->context);
fprintf(f, " Our keyid: %u\n", auth->our_keyid);
fprintf(f, " Their keyid: %u\n", auth->their_keyid);
......@@ -346,7 +344,6 @@ gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
switch(auth->authstate) {
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_SIG:
case OTRL_AUTHSTATE_V1_SETUP:
/* Store the incoming information */
otrl_auth_clear(auth);
auth->protocol_version = version;
......@@ -872,7 +869,6 @@ gcry_error_t otrl_auth_handle_key(OtrlAuthInfo *auth, const char *keymsg,
break;
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
case OTRL_AUTHSTATE_V1_SETUP:
/* Ignore this message */
*havemsgp = 0;
break;
......@@ -1046,7 +1042,6 @@ gcry_error_t otrl_auth_handle_revealsig(OtrlAuthInfo *auth,
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_DHKEY:
case OTRL_AUTHSTATE_AWAITING_SIG:
case OTRL_AUTHSTATE_V1_SETUP:
/* Ignore this message */
*havemsgp = 0;
free(buf);
......@@ -1160,7 +1155,6 @@ gcry_error_t otrl_auth_handle_signature(OtrlAuthInfo *auth,
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_DHKEY:
case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
case OTRL_AUTHSTATE_V1_SETUP:
/* Ignore this message */
*havemsgp = 0;
free(buf);
......@@ -1180,264 +1174,6 @@ err:
return err;
}
/* Version 1 routines, for compatibility */
/*
* Create a verion 1 Key Exchange Message using the values in the given
* auth, and store it in auth->lastauthmsg. Set the Reply field to the
* given value, and use the given privkey to sign the message.
*/
static gcry_error_t create_v1_key_exchange_message(OtrlAuthInfo *auth,
unsigned char reply, OtrlPrivKey *privkey)
{
gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
unsigned char *buf = NULL, *bufp = NULL, *sigbuf = NULL;
size_t lenp, ourpublen, totallen, siglen;
unsigned char hashbuf[20];
if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA) {
return gpg_error(GPG_ERR_INV_VALUE);
}
/* How big is the DH public key? */
gcry_mpi_print(format, NULL, 0, &ourpublen, auth->our_dh.pub);
totallen = 3 + 1 + privkey->pubkey_datalen + 4 + 4 + ourpublen + 40;
buf = malloc(totallen);
if (buf == NULL) goto memerr;
bufp = buf;
lenp = totallen;
memmove(bufp, "\x00\x01\x0a", 3); /* header */
debug_data("Header", bufp, 3);
bufp += 3; lenp -= 3;
bufp[0] = reply;
debug_data("Reply", bufp, 1);
bufp += 1; lenp -= 1;
memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
debug_data("Pubkey", bufp, privkey->pubkey_datalen);
bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
write_int(auth->our_keyid);
debug_int("Keyid", bufp-4);
write_mpi(auth->our_dh.pub, ourpublen, "D-H y");
/* Hash all the data written so far, and sign the hash */
gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
err = otrl_privkey_sign(&sigbuf, &siglen, privkey, hashbuf, 20);
if (err) goto err;
if (siglen != 40) goto invval;
memmove(bufp, sigbuf, 40);
debug_data("Signature", bufp, 40);
bufp += 40; lenp -= 40;
free(sigbuf);
sigbuf = NULL;
assert(lenp == 0);
free(auth->lastauthmsg);
auth->lastauthmsg = otrl_base64_otr_encode(buf, totallen);
if (auth->lastauthmsg == NULL) goto memerr;
free(buf);
buf = NULL;
return err;
invval:
err = gcry_error(GPG_ERR_INV_VALUE);
goto err;
memerr:
err = gcry_error(GPG_ERR_ENOMEM);
err:
free(buf);
free(sigbuf);
return err;
}
/*
* Start a fresh AKE (version 1) using the given OtrlAuthInfo. If
* our_dh is NULL, generate a fresh DH keypair to use. Otherwise, use a
* copy of the one passed (with the given keyid). Use the given private
* key to sign the message. If no error is returned, the message to
* transmit will be contained in auth->lastauthmsg.
*/
gcry_error_t otrl_auth_start_v1(OtrlAuthInfo *auth, DH_keypair *our_dh,
unsigned int our_keyid, OtrlPrivKey *privkey)
{
gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
/* Clear out this OtrlAuthInfo and start over */
otrl_auth_clear(auth);
auth->initiated = 1;
auth->protocol_version = 1;
/* Import the given DH keypair, or else create a fresh one */
if (our_dh) {
otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
auth->our_keyid = our_keyid;
} else {
otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
auth->our_keyid = 1;
}
err = create_v1_key_exchange_message(auth, 0, privkey);
if (!err) {
auth->authstate = OTRL_AUTHSTATE_V1_SETUP;
}
return err;
}
/*
* Handle an incoming v1 Key Exchange Message. If no error is returned,
* and *havemsgp is 1, the message to be sent will be left in
* auth->lastauthmsg. Use the given private authentication key to sign
* messages. Call the auth_secceeded callback if authentication is
* successful. If non-NULL, use a copy of the given D-H keypair, with
* the given keyid.
*/
gcry_error_t otrl_auth_handle_v1_key_exchange(OtrlAuthInfo *auth,
const char *keyexchmsg, int *havemsgp, OtrlPrivKey *privkey,
DH_keypair *our_dh, unsigned int our_keyid,
gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
void *asdata)
{
gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
unsigned char *buf = NULL, *bufp = NULL;
unsigned char *fingerprintstart, *fingerprintend;
unsigned char fingerprintbuf[20], hashbuf[20];
gcry_mpi_t p, q, g, y, received_pub = NULL;
gcry_sexp_t pubs = NULL;
size_t buflen, lenp;
unsigned char received_reply;
unsigned int received_keyid;
int res;
*havemsgp = 0;
res = otrl_base64_otr_decode(keyexchmsg, &buf, &buflen);
if (res == -1) goto memerr;
if (res == -2) goto invval;
bufp = buf;
lenp = buflen;
/* Header */
require_len(3);
if (memcmp(bufp, "\x00\x01\x0a", 3)) goto invval;
bufp += 3; lenp -= 3;
/* Reply */
require_len(1);
received_reply = bufp[0];
bufp += 1; lenp -= 1;
/* Public Key */
fingerprintstart = bufp;
read_mpi(p);
read_mpi(q);
read_mpi(g);
read_mpi(y);
fingerprintend = bufp;
gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbuf,
fingerprintstart, fingerprintend-fingerprintstart);
gcry_sexp_build(&pubs, NULL,
"(public-key (dsa (p %m)(q %m)(g %m)(y %m)))", p, q, g, y);
gcry_mpi_release(p);
gcry_mpi_release(q);
gcry_mpi_release(g);
gcry_mpi_release(y);
/* keyid */
read_int(received_keyid);
if (received_keyid == 0) goto invval;
/* D-H pubkey */
read_mpi(received_pub);
/* Verify the signature */
if (lenp != 40) goto invval;
gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
err = otrl_privkey_verify(bufp, lenp, OTRL_PUBKEY_TYPE_DSA,
pubs, hashbuf, 20);
if (err) goto err;
gcry_sexp_release(pubs);
pubs = NULL;
free(buf);
buf = NULL;
if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP && received_reply == 0x01) {
/* They're replying to something we never sent. We must be
* logged in more than once; ignore the message. */
err = gpg_error(GPG_ERR_NO_ERROR);
goto err;
}
if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP) {
/* Clear the auth and start over */
otrl_auth_clear(auth);
}
/* Everything checked out */
auth->their_keyid = received_keyid;
gcry_mpi_release(auth->their_pub);
auth->their_pub = received_pub;
received_pub = NULL;
memmove(auth->their_fingerprint, fingerprintbuf, 20);
if (received_reply == 0x01) {
/* Don't send a reply to this. */
*havemsgp = 0;
} else {
/* Import the given DH keypair, or else create a fresh one */
if (our_dh) {
otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
auth->our_keyid = our_keyid;
} else if (auth->our_keyid == 0) {
otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
auth->our_keyid = 1;
}
/* Reply with our own Key Exchange Message */
err = create_v1_key_exchange_message(auth, 1, privkey);
if (err) goto err;
*havemsgp = 1;
}
/* Compute the session id */
err = otrl_dh_compute_v1_session_id(&(auth->our_dh),
auth->their_pub, auth->secure_session_id,
&(auth->secure_session_id_len),
&(auth->session_id_half));
if (err) goto err;
/* We've completed our end of the authentication */
auth->protocol_version = 1;
if (auth_succeeded) err = auth_succeeded(auth, asdata);
auth->our_keyid = 0;
auth->authstate = OTRL_AUTHSTATE_NONE;
return err;
invval:
err = gcry_error(GPG_ERR_INV_VALUE);
goto err;
memerr:
err = gcry_error(GPG_ERR_ENOMEM);
err:
free(buf);
gcry_sexp_release(pubs);
gcry_mpi_release(received_pub);
return err;
}
/*
* Copy relevant information from the master OtrlAuthInfo to an
* instance OtrlAuthInfo in response to a D-H Key with a new
......@@ -1542,29 +1278,6 @@ int main(int argc, char **argv)
starting, "Bob");
CHECK_ERR
printf("\n\n ***** V1 *****\n\n");
err = otrl_auth_start_v1(&bob, NULL, 0, bobpriv);
CHECK_ERR
printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
err = otrl_auth_handle_v1_key_exchange(&alice, bob.lastauthmsg,
&havemsg, alicepriv, NULL, 0, starting, "Alice");
CHECK_ERR
if (havemsg) {
printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg),
alice.lastauthmsg);
} else {
printf("\nIGNORE\n\n");
}
err = otrl_auth_handle_v1_key_exchange(&bob, alice.lastauthmsg,
&havemsg, bobpriv, NULL, 0, starting, "Bob");
CHECK_ERR
if (havemsg) {
printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
} else {
printf("\nIGNORE\n\n");
}
otrl_userstate_free(us);
otrl_auth_clear(&alice);
otrl_auth_clear(&bob);
......
......@@ -31,7 +31,6 @@ typedef enum {
OTRL_AUTHSTATE_AWAITING_DHKEY,
OTRL_AUTHSTATE_AWAITING_REVEALSIG,
OTRL_AUTHSTATE_AWAITING_SIG,
OTRL_AUTHSTATE_V1_SETUP
} OtrlAuthState;
typedef struct {
......@@ -67,8 +66,7 @@ typedef struct {
unsigned char secure_session_id[20]; /* The secure session id */
size_t secure_session_id_len; /* And its actual length,
which may be either 20 (for
v1) or 8 (for v2) */
which may is 20 (for v2) */
OtrlSessionIdHalf session_id_half; /* Which half of the session
id gets shown in bold */
......@@ -142,30 +140,6 @@ gcry_error_t otrl_auth_handle_signature(OtrlAuthInfo *auth,
gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
void *asdata);
/*
* Start a fresh AKE (version 1) using the given OtrlAuthInfo. If
* our_dh is NULL, generate a fresh DH keypair to use. Otherwise, use a
* copy of the one passed (with the given keyid). Use the given private
* key to sign the message. If no error is returned, the message to
* transmit will be contained in auth->lastauthmsg.
*/
gcry_error_t otrl_auth_start_v1(OtrlAuthInfo *auth, DH_keypair *our_dh,
unsigned int our_keyid, OtrlPrivKey *privkey);
/*
* Handle an incoming v1 Key Exchange Message. If no error is returned,
* and *havemsgp is 1, the message to be sent will be left in
* auth->lastauthmsg. Use the given private authentication key to sign
* messages. Call the auth_secceeded callback if authentication is
* successful. If non-NULL, use a copy of the given D-H keypair, with
* the given keyid.
*/
gcry_error_t otrl_auth_handle_v1_key_exchange(OtrlAuthInfo *auth,
const char *keyexchmsg, int *havemsgp, OtrlPrivKey *privkey,
DH_keypair *our_dh, unsigned int our_keyid,
gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
void *asdata);
/*
* Copy relevant information from the master OtrlAuthInfo to an
* instance OtrlAuthInfo in response to a D-H Key with a new
......
......@@ -356,72 +356,6 @@ err:
return err;
}
/*
* Compute the secure session id, given our DH key and their DH public
* key.
*/
gcry_error_t otrl_dh_compute_v1_session_id(const DH_keypair *our_dh,
gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
OtrlSessionIdHalf *halfp)
{
gcry_mpi_t s;
size_t slen;
unsigned char *sdata;
unsigned char *hashdata;
if (our_dh->groupid != DH1536_GROUP_ID) {
/* Invalid group id */
return gcry_error(GPG_ERR_INV_VALUE);
}
/* Check that their_pub is in range */
if (gcry_mpi_cmp_ui(their_pub, 2) < 0 ||
gcry_mpi_cmp(their_pub, DH1536_MODULUS_MINUS_2) > 0) {
/* Invalid pubkey */
return gcry_error(GPG_ERR_INV_VALUE);
}
/* Calculate the shared secret MPI */
s = gcry_mpi_snew(DH1536_MOD_LEN_BITS);
gcry_mpi_powm(s, their_pub, our_dh->priv, DH1536_MODULUS);
/* Output it in the right format */
gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &slen, s);
sdata = gcry_malloc_secure(slen + 5);
if (!sdata) {
gcry_mpi_release(s);
return gcry_error(GPG_ERR_ENOMEM);
}
sdata[1] = (slen >> 24) & 0xff;
sdata[2] = (slen >> 16) & 0xff;
sdata[3] = (slen >> 8) & 0xff;
sdata[4] = slen & 0xff;
gcry_mpi_print(GCRYMPI_FMT_USG, sdata+5, slen, NULL, s);
gcry_mpi_release(s);
/* Calculate the session id */
hashdata = gcry_malloc_secure(20);
if (!hashdata) {
gcry_free(sdata);
return gcry_error(GPG_ERR_ENOMEM);
}
sdata[0] = 0x00;
gcry_md_hash_buffer(GCRY_MD_SHA1, hashdata, sdata, slen+5);
memmove(sessionid, hashdata, 20);
*sessionidlenp = 20;
/* Which half should be bold? */
if (gcry_mpi_cmp(our_dh->pub, their_pub) > 0) {
*halfp = OTRL_SESSIONID_SECOND_HALF_BOLD;
} else {
*halfp = OTRL_SESSIONID_FIRST_HALF_BOLD;
}
gcry_free(hashdata);
gcry_free(sdata);
return gcry_error(GPG_ERR_NO_ERROR);
}
/*
* Deallocate the contents of a DH_sesskeys (but not the DH_sesskeys
* itself)
......
......@@ -94,14 +94,6 @@ gcry_error_t otrl_dh_compute_v2_auth_keys(const DH_keypair *our_dh,
gcry_md_hd_t *mac_m1, gcry_md_hd_t *mac_m1p,
gcry_md_hd_t *mac_m2, gcry_md_hd_t *mac_m2p);
/*
* Compute the secure session id, given our DH key and their DH public
* key.
*/
gcry_error_t otrl_dh_compute_v1_session_id(const DH_keypair *our_dh,
gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
OtrlSessionIdHalf *halfp);
/*
* Deallocate the contents of a DH_sesskeys (but not the DH_sesskeys
* itself)
......
......@@ -337,27 +337,21 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
* if he responds. */
size_t msglen = strlen(original_msg);
size_t basetaglen = strlen(OTRL_MESSAGE_TAG_BASE);
size_t v1taglen = (policy & OTRL_POLICY_ALLOW_V1) ?
strlen(OTRL_MESSAGE_TAG_V1) : 0;
size_t v2taglen = (policy & OTRL_POLICY_ALLOW_V2) ?
strlen(OTRL_MESSAGE_TAG_V2) : 0;
size_t v3taglen = (policy & OTRL_POLICY_ALLOW_V3) ?
strlen(OTRL_MESSAGE_TAG_V3) : 0;
char *taggedmsg = malloc(msglen + basetaglen + v1taglen
+ v2taglen + v3taglen + 1);
char *taggedmsg = malloc(msglen + basetaglen + v2taglen + v3taglen
+ 1);
if (taggedmsg) {
strcpy(taggedmsg, original_msg);
strcpy(taggedmsg + msglen, OTRL_MESSAGE_TAG_BASE);
if (v1taglen) {
strcpy(taggedmsg + msglen + basetaglen,
OTRL_MESSAGE_TAG_V1);
}
if (v2taglen) {
strcpy(taggedmsg + msglen + basetaglen + v1taglen,
strcpy(taggedmsg + msglen + basetaglen + v2taglen,
OTRL_MESSAGE_TAG_V2);
}
if (v3taglen) {
strcpy(taggedmsg + msglen + basetaglen + v1taglen
strcpy(taggedmsg + msglen + basetaglen + v2taglen
+ v2taglen, OTRL_MESSAGE_TAG_V3);
}
*messagep = taggedmsg;
......@@ -1046,8 +1040,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
/* Check that this version is allowed by the policy */
if (((version == 3) && !(policy & OTRL_POLICY_ALLOW_V3))
|| ((version == 2) && !(policy & OTRL_POLICY_ALLOW_V2))
|| ((version == 1) && !(policy & OTRL_POLICY_ALLOW_V1))) {
|| ((version == 2) && !(policy & OTRL_POLICY_ALLOW_V2))) {
edata.ignore_message = 1;
goto end;
}
......@@ -1171,25 +1164,6 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
err = otrl_auth_start_v23(&(context->auth), 2);
send_or_error_auth(ops, opdata, err, context, us);
break;
case 1:
/* Get our private key */
privkey = otrl_privkey_find(us, context->accountname,
context->protocol);
if (privkey == NULL) {
/* We've got no private key! */
if (ops->create_privkey) {
ops->create_privkey(opdata, context->accountname,
context->protocol);
privkey = otrl_privkey_find(us,
context->accountname, context->protocol);
}
}
if (privkey) {
err = otrl_auth_start_v1(&(context->auth), our_dh,
our_keyid, privkey);
send_or_error_auth(ops, opdata, err, context, us);