mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 03:50:57 +01:00
added checks to avoid overflows caused by user supplied field sizes
This commit is contained in:
@@ -145,7 +145,7 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
|
|||||||
else {
|
else {
|
||||||
/* step 1, check header */
|
/* step 1, check header */
|
||||||
cur_bufsize = ps_read(in, head, 1); /* fread(head, 1, 1, in); */
|
cur_bufsize = ps_read(in, head, 1); /* fread(head, 1, 1, in); */
|
||||||
if(cur_bufsize != 1 && !ps_end(in) && !ps_err(in)) {
|
if(cur_bufsize == 1 && !ps_end(in) && !ps_err(in)) {
|
||||||
if(head[0] == PCP_SYM_CIPHER) {
|
if(head[0] == PCP_SYM_CIPHER) {
|
||||||
if(symkey != NULL)
|
if(symkey != NULL)
|
||||||
self = 1;
|
self = 1;
|
||||||
@@ -206,7 +206,8 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
|
|||||||
for(nrec=0; nrec<lenrec; nrec++) {
|
for(nrec=0; nrec<lenrec; nrec++) {
|
||||||
cur_bufsize = ps_read(in, rec_buf, PCP_ASYM_RECIPIENT_SIZE);
|
cur_bufsize = ps_read(in, rec_buf, PCP_ASYM_RECIPIENT_SIZE);
|
||||||
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
|
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
|
||||||
fatal(ptx, "Error: input file corrupted, incomplete or no recipients (got %ld, exp %ld)\n", cur_bufsize, PCP_ASYM_RECIPIENT_SIZE );
|
fatal(ptx, "Error: input file corrupted, incomplete or no recipients (got %ld, exp %ld)\n",
|
||||||
|
cur_bufsize, PCP_ASYM_RECIPIENT_SIZE );
|
||||||
ucfree(rec_buf, PCP_ASYM_RECIPIENT_SIZE);
|
ucfree(rec_buf, PCP_ASYM_RECIPIENT_SIZE);
|
||||||
goto errdef1;
|
goto errdef1;
|
||||||
}
|
}
|
||||||
@@ -691,6 +692,12 @@ uint64_t _get_nonce_ctr(byte *nonce) {
|
|||||||
uint8_t i = nonce[0];
|
uint8_t i = nonce[0];
|
||||||
uint16_t m16 = 0;
|
uint16_t m16 = 0;
|
||||||
uint32_t m32 = 0;
|
uint32_t m32 = 0;
|
||||||
|
|
||||||
|
if(i > 16) {
|
||||||
|
/* counter bigger than max allowed by protocol, could lead to overflow, therefore die hard here */
|
||||||
|
fprintf(stderr, "invalid counter size %d!", i);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader) {
|
int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader) {
|
||||||
|
uint16_t nsize, vsize;
|
||||||
|
char *notation = NULL;
|
||||||
|
|
||||||
if(subheader->size > buffer_left(blob)) {
|
if(subheader->size > buffer_left(blob)) {
|
||||||
fatal(ptx, "Invalid header size %ld specified in source\n", subheader->size);
|
fatal(ptx, "Invalid header size %ld specified in source\n", subheader->size);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -77,44 +80,44 @@ int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *su
|
|||||||
|
|
||||||
if(subheader->type == EXP_SIG_SUB_NOTATION) {
|
if(subheader->type == EXP_SIG_SUB_NOTATION) {
|
||||||
/* mail or owner */
|
/* mail or owner */
|
||||||
uint16_t nsize = buffer_get16na(blob);
|
nsize = buffer_get16na(blob);
|
||||||
uint16_t vsize = buffer_get16na(blob);
|
vsize = buffer_get16na(blob);
|
||||||
|
|
||||||
char *notation = ucmalloc(nsize+1);
|
|
||||||
|
|
||||||
if(nsize > buffer_left(blob)) {
|
if(nsize > buffer_left(blob)) {
|
||||||
fatal(ptx, "Invalid notation size %ld specified in source\n", nsize);
|
fatal(ptx, "Invalid notation size %ld specified in source\n", nsize);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notation = ucmalloc(nsize+1);
|
||||||
|
|
||||||
if(buffer_get_chunk(blob, notation, nsize) == 0) {
|
if(buffer_get_chunk(blob, notation, nsize) == 0) {
|
||||||
fatal(ptx, "Invalid notation size, expected %ld bytes, but got 0\n", nsize);
|
fatal(ptx, "Invalid notation size, expected %ld bytes, but got 0\n", nsize);
|
||||||
return 1;
|
goto sgcerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
notation[nsize] = '\0';
|
notation[nsize] = '\0';
|
||||||
|
|
||||||
if(vsize > buffer_left(blob)) {
|
if(vsize > buffer_left(blob) || vsize > 255) {
|
||||||
fatal(ptx, "Invalid notation value size %ld specified in source\n", vsize);
|
fatal(ptx, "Invalid notation value size %ld specified in source\n", vsize);
|
||||||
return 1;
|
goto sgcerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strncmp(notation, "owner", 5) == 0) {
|
if(strncmp(notation, "owner", 5) == 0) {
|
||||||
if(buffer_get_chunk(blob, p->owner, vsize) == 0) {
|
if(buffer_get_chunk(blob, p->owner, vsize) == 0) {
|
||||||
fatal(ptx, "Invalid 'owner' notation, expected %ld bytes, but got 0\n", vsize);
|
fatal(ptx, "Invalid 'owner' notation, expected %ld bytes, but got 0\n", vsize);
|
||||||
return 1;
|
goto sgcerr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(strncmp(notation, "mail", 4) == 0) {
|
else if(strncmp(notation, "mail", 4) == 0) {
|
||||||
if(buffer_get_chunk(blob, p->mail, vsize) == 0) {
|
if(buffer_get_chunk(blob, p->mail, vsize) == 0) {
|
||||||
fatal(ptx, "Invalid 'mail' notation, expected %ld bytes, but got 0\n", vsize);
|
fatal(ptx, "Invalid 'mail' notation, expected %ld bytes, but got 0\n", vsize);
|
||||||
return 1;
|
goto sgcerr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(strncmp(notation, "serial", 6) == 0) {
|
else if(strncmp(notation, "serial", 6) == 0) {
|
||||||
p->serial = buffer_get32na(blob);
|
p->serial = buffer_get32na(blob);
|
||||||
}
|
}
|
||||||
ucfree(notation, nsize);
|
ucfree(notation, nsize+1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* unsupported or ignored sig subs:
|
/* unsupported or ignored sig subs:
|
||||||
@@ -129,8 +132,11 @@ int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *su
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
sgcerr:
|
||||||
|
ucfree(notation, nsize+1);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t *sk) {
|
int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t *sk) {
|
||||||
@@ -814,7 +820,7 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
|
|||||||
byte *symkey = NULL;
|
byte *symkey = NULL;
|
||||||
byte *clear = NULL;
|
byte *clear = NULL;
|
||||||
size_t cipherlen = 0;
|
size_t cipherlen = 0;
|
||||||
size_t minlen = (64 * 2) + (32 * 4) + 8 + 4 + 4;
|
size_t minlen = (64 * 2) + (32 * 4) + 8 + 4 + 4; /* key material and mandatory field sizes */
|
||||||
uint16_t notationlen = 0;
|
uint16_t notationlen = 0;
|
||||||
|
|
||||||
Buffer *blob = buffer_new(512, "secretdecryptbuf");
|
Buffer *blob = buffer_new(512, "secretdecryptbuf");
|
||||||
@@ -853,11 +859,19 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras
|
|||||||
buffer_get_chunk(blob, sk->edpub, 32);
|
buffer_get_chunk(blob, sk->edpub, 32);
|
||||||
|
|
||||||
notationlen = buffer_get16na(blob);
|
notationlen = buffer_get16na(blob);
|
||||||
if(notationlen > 0)
|
if(notationlen > 255) {
|
||||||
|
fatal(ptx, "Invalid notation value size for owner\n");
|
||||||
|
goto impserr2;
|
||||||
|
}
|
||||||
|
else if(notationlen > 0)
|
||||||
buffer_get_chunk(blob, sk->owner, notationlen);
|
buffer_get_chunk(blob, sk->owner, notationlen);
|
||||||
|
|
||||||
notationlen = buffer_get16na(blob);
|
notationlen = buffer_get16na(blob);
|
||||||
if(notationlen > 0)
|
if(notationlen > 255) {
|
||||||
|
fatal(ptx, "Invalid notation value size for mail\n");
|
||||||
|
goto impserr2;
|
||||||
|
}
|
||||||
|
else if(notationlen > 0)
|
||||||
buffer_get_chunk(blob, sk->mail, notationlen);
|
buffer_get_chunk(blob, sk->mail, notationlen);
|
||||||
|
|
||||||
if(buffer_done(blob) == 1)
|
if(buffer_done(blob) == 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user