mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-22 07:41:20 -04:00

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-OpenPGP@5260 b45a01b8-16f6-495d-af2f-9b41ad6348cc
248 lines
6.8 KiB
C
248 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
|
* All rights reserved.
|
|
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
|
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
|
* be recorded as the authors of this copyright work.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
* use this file except in compliance with the License.
|
|
*
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/** \file
|
|
* \brief Parser for OpenPGP packets
|
|
*/
|
|
|
|
#include <openssl/cast.h>
|
|
|
|
#include <openpgpsdk/callback.h>
|
|
#include <openpgpsdk/packet.h>
|
|
#include <openpgpsdk/packet-parse.h>
|
|
#include <openpgpsdk/keyring.h>
|
|
#include <openpgpsdk/util.h>
|
|
#include <openpgpsdk/compress.h>
|
|
#include <openpgpsdk/errors.h>
|
|
#include <openpgpsdk/readerwriter.h>
|
|
#include <openpgpsdk/packet-show.h>
|
|
#include <openpgpsdk/std_print.h>
|
|
#include <openpgpsdk/create.h>
|
|
#include <openpgpsdk/hash.h>
|
|
|
|
#include "parse_local.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#endif
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
|
|
#include <openpgpsdk/final.h>
|
|
|
|
static int debug=0;
|
|
|
|
typedef struct
|
|
{
|
|
// boolean: false once we've done the preamble/MDC checks
|
|
// and are reading from the plaintext
|
|
int passed_checks;
|
|
unsigned char *plaintext;
|
|
size_t plaintext_available;
|
|
size_t plaintext_offset;
|
|
ops_region_t *region;
|
|
ops_crypt_t *decrypt;
|
|
} decrypt_se_ip_arg_t;
|
|
|
|
static int se_ip_data_reader(void *dest_, size_t len, ops_error_t **errors,
|
|
ops_reader_info_t *rinfo,
|
|
ops_parse_cb_info_t *cbinfo)
|
|
{
|
|
|
|
/*
|
|
Gets entire SE_IP data packet.
|
|
Verifies leading preamble
|
|
Verifies trailing MDC packet
|
|
Then passes up plaintext as requested
|
|
*/
|
|
|
|
unsigned int n=0;
|
|
|
|
ops_region_t decrypted_region;
|
|
|
|
decrypt_se_ip_arg_t *arg=ops_reader_get_arg(rinfo);
|
|
|
|
if (!arg->passed_checks)
|
|
{
|
|
unsigned char*buf=NULL;
|
|
|
|
ops_hash_t hash;
|
|
unsigned char hashed[SHA_DIGEST_LENGTH];
|
|
|
|
size_t b;
|
|
size_t sz_preamble;
|
|
size_t sz_mdc_hash;
|
|
size_t sz_mdc;
|
|
size_t sz_plaintext;
|
|
|
|
unsigned char* preamble;
|
|
unsigned char* plaintext;
|
|
unsigned char* mdc;
|
|
unsigned char* mdc_hash;
|
|
|
|
ops_hash_any(&hash,OPS_HASH_SHA1);
|
|
hash.init(&hash);
|
|
|
|
ops_init_subregion(&decrypted_region,NULL);
|
|
decrypted_region.length = arg->region->length - arg->region->length_read;
|
|
buf=ops_mallocz(decrypted_region.length);
|
|
|
|
// read entire SE IP packet
|
|
|
|
if (!ops_stacked_limited_read(buf,decrypted_region.length, &decrypted_region,errors,rinfo,cbinfo))
|
|
{
|
|
free (buf);
|
|
return -1;
|
|
}
|
|
|
|
if (debug)
|
|
{
|
|
unsigned int i=0;
|
|
fprintf(stderr,"\n\nentire SE IP packet (len=%d):\n",decrypted_region.length);
|
|
for (i=0; i<decrypted_region.length; i++)
|
|
{
|
|
fprintf(stderr,"0x%02x ", buf[i]);
|
|
if (!((i+1)%8))
|
|
fprintf(stderr,"\n");
|
|
}
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,"\n");
|
|
}
|
|
|
|
// verify leading preamble
|
|
|
|
if (debug)
|
|
{
|
|
unsigned int i=0;
|
|
fprintf(stderr,"\npreamble: ");
|
|
for (i=0; i<arg->decrypt->blocksize+2;i++)
|
|
fprintf(stderr," 0x%02x", buf[i]);
|
|
fprintf(stderr,"\n");
|
|
}
|
|
|
|
b=arg->decrypt->blocksize;
|
|
if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1])
|
|
{
|
|
fprintf(stderr,"Bad symmetric decrypt (%02x%02x vs %02x%02x)\n",
|
|
buf[b-2],buf[b-1],buf[b],buf[b+1]);
|
|
OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT,"Bad symmetric decrypt when parsing SE IP packet");
|
|
free(buf);
|
|
return -1;
|
|
}
|
|
|
|
// Verify trailing MDC hash
|
|
|
|
sz_preamble=arg->decrypt->blocksize+2;
|
|
sz_mdc_hash=OPS_SHA1_HASH_SIZE;
|
|
sz_mdc=1+1+sz_mdc_hash;
|
|
sz_plaintext=decrypted_region.length-sz_preamble-sz_mdc;
|
|
|
|
preamble=buf;
|
|
plaintext=buf+sz_preamble;
|
|
mdc=plaintext+sz_plaintext;
|
|
mdc_hash=mdc+2;
|
|
|
|
#ifdef DEBUG
|
|
if (debug)
|
|
{
|
|
unsigned int i=0;
|
|
|
|
fprintf(stderr,"\nplaintext (len=%ld): ",sz_plaintext);
|
|
for (i=0; i<sz_plaintext;i++)
|
|
fprintf(stderr," 0x%02x", plaintext[i]);
|
|
fprintf(stderr,"\n");
|
|
|
|
fprintf(stderr,"\nmdc (len=%ld): ",sz_mdc);
|
|
for (i=0; i<sz_mdc;i++)
|
|
fprintf(stderr," 0x%02x", mdc[i]);
|
|
fprintf(stderr,"\n");
|
|
}
|
|
#endif /*DEBUG*/
|
|
|
|
ops_calc_mdc_hash(preamble,sz_preamble,plaintext,sz_plaintext,&hashed[0]);
|
|
|
|
if (memcmp(mdc_hash,hashed,OPS_SHA1_HASH_SIZE))
|
|
{
|
|
OPS_ERROR(errors, OPS_E_V_BAD_HASH, "Bad hash in MDC packet");
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
// all done with the checks
|
|
// now can start reading from the plaintext
|
|
assert(!arg->plaintext);
|
|
arg->plaintext=ops_mallocz(sz_plaintext);
|
|
memcpy(arg->plaintext, plaintext, sz_plaintext);
|
|
arg->plaintext_available=sz_plaintext;
|
|
|
|
arg->passed_checks=1;
|
|
|
|
free(buf);
|
|
}
|
|
|
|
n=len;
|
|
if (n > arg->plaintext_available)
|
|
n=arg->plaintext_available;
|
|
|
|
memcpy(dest_, arg->plaintext+arg->plaintext_offset, n);
|
|
arg->plaintext_available-=n;
|
|
arg->plaintext_offset+=n;
|
|
len-=n;
|
|
|
|
return n;
|
|
}
|
|
|
|
static void se_ip_data_destroyer(ops_reader_info_t *rinfo)
|
|
{
|
|
decrypt_se_ip_arg_t* arg=ops_reader_get_arg(rinfo);
|
|
free (arg->plaintext);
|
|
free (arg);
|
|
// free(ops_reader_get_arg(rinfo));
|
|
}
|
|
|
|
/**
|
|
\ingroup Internal_Readers_SEIP
|
|
*/
|
|
void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt,
|
|
ops_region_t *region)
|
|
{
|
|
decrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
|
|
arg->region=region;
|
|
arg->decrypt=decrypt;
|
|
|
|
ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer,arg);
|
|
}
|
|
|
|
/**
|
|
\ingroup Internal_Readers_SEIP
|
|
*/
|
|
void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo)
|
|
{
|
|
// decrypt_se_ip_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
|
|
// free(arg);
|
|
ops_reader_pop(pinfo);
|
|
}
|
|
|
|
// eof
|