Ejemplo n.º 1
0
static int calc_and_compare_checksum(const unsigned char *buf, size_t len,
                                     uint32_t expected)
{
    const uint16_t *buf16 = (const uint16_t *) buf;
    size_t len16 = len/2;
    uint32_t result = fletcher32(buf16, len16);

    return result == expected;
}
Ejemplo n.º 2
0
static void test_checksum_fletcher32_0to1_undetected(void)
{
    /* fletcher cannot distinguish between all 0 and all 1 segments */
    unsigned char buf0[16] = {
        0xA1, 0xA1, 0xA1, 0xA1,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x1A, 0x1A, 0x1A, 0x1A,
    };
    uint32_t expect = fletcher32((const uint16_t *) buf0, sizeof(buf0)/2);
    unsigned char buf1[16] = {
        0xA1, 0xA1, 0xA1, 0xA1,
        0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF,
        0x1A, 0x1A, 0x1A, 0x1A,
    };

    TEST_ASSERT(calc_and_compare_checksum(buf1, sizeof(buf1), expect));
}
Ejemplo n.º 3
0
Archivo: hdr.c Proyecto: RIOT-OS/RIOT
uint32_t riotboot_hdr_checksum(const riotboot_hdr_t *riotboot_hdr)
{
    return fletcher32((uint16_t *)riotboot_hdr, offsetof(riotboot_hdr_t, chksum) / sizeof(uint16_t));
}
int compress_block_generic(struct s_blockinfo *blkinfo)
{
    char *bufcomp=NULL;
    int attempt=0;
    int compalgo;
    int complevel;
    u64 compsize;
    u64 bufsize;
    int res;
    
    bufsize = (blkinfo->blkrealsize) + (blkinfo->blkrealsize / 16) + 64 + 3; // alloc bigger buffer else lzo will crash
    if ((bufcomp=malloc(bufsize))==NULL)
    {   errprintf("malloc(%ld) failed: out of memory\n", (long)bufsize);
        return -1;
    }
    
    // compression level/algo to use for the first attempt
    compalgo=g_options.compressalgo;
    complevel=g_options.compresslevel;
    
    // compress the block
    do
    {
        switch (compalgo)
        {
#ifdef OPTION_LZO_SUPPORT
            case COMPRESS_LZO:
                res=compress_block_lzo(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel);
                blkinfo->blkcompalgo=COMPRESS_LZO;
                break;
#endif // OPTION_LZO_SUPPORT
            case COMPRESS_GZIP:
                res=compress_block_gzip(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel);
                blkinfo->blkcompalgo=COMPRESS_GZIP;
                break;
            case COMPRESS_BZIP2:
                res=compress_block_bzip2(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel);
                blkinfo->blkcompalgo=COMPRESS_BZIP2;
                break;
#ifdef OPTION_LZMA_SUPPORT
            case COMPRESS_LZMA:
                res=compress_block_lzma(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel);
                blkinfo->blkcompalgo=COMPRESS_LZMA;
                break;
#endif // OPTION_LZMA_SUPPORT
            default:
                free(bufcomp);
                msgprintf(2, "invalid compression level: %d\n", (int)compalgo);
                return -1;
        }
        
        // retry if high compression was used and compression failed because of FSAERR_ENOMEM
        if ((res == FSAERR_ENOMEM) && (compalgo > FSA_DEF_COMPRESS_ALGO))
        {
            errprintf("attempt to compress the current block using an alternative algorithm (\"-z%d\")\n", FSA_DEF_COMPRESS_ALGO);
            compalgo = FSA_DEF_COMPRESS_ALGO;
            complevel = FSA_DEF_COMPRESS_LEVEL;
        }
        
    } while ((res == FSAERR_ENOMEM) && (attempt++ == 0));
    
    // check compression status and efficiency
    if ((res==FSAERR_SUCCESS) && (compsize < blkinfo->blkrealsize)) // compression worked and saved space
    {   free(blkinfo->blkdata); // free old buffer (with uncompressed data)
        blkinfo->blkdata=bufcomp; // new buffer (with compressed data)
        blkinfo->blkcompsize=compsize; // size after compression and before encryption
        blkinfo->blkarsize=compsize; // in case there is no encryption to set this
        //errprintf ("COMP_DBG: block successfully compressed using %s\n", compress_algo_int_to_string(compalgo));
    }
    else // compressed version is bigger or compression failed: keep the original block
    {   memcpy(bufcomp, blkinfo->blkdata, blkinfo->blkrealsize);
        free(blkinfo->blkdata); // free old buffer
        blkinfo->blkdata=bufcomp; // new buffer
        blkinfo->blkcompsize=blkinfo->blkrealsize; // size after compression and before encryption
        blkinfo->blkarsize=blkinfo->blkrealsize;  // in case there is no encryption to set this
        blkinfo->blkcompalgo=COMPRESS_NONE;
        //errprintf ("COMP_DBG: block copied uncompressed, attempted using %s\n", compress_algo_int_to_string(compalgo));
    }
    
    u64 cryptsize;
    char *bufcrypt=NULL;
    if (g_options.encryptalgo==ENCRYPT_BLOWFISH)
    {
        if ((bufcrypt=malloc(bufsize+8))==NULL)
        {   errprintf("malloc(%ld) failed: out of memory\n", (long)bufsize+8);
            return -1;
        }
        if ((res=crypto_blowfish(blkinfo->blkcompsize, &cryptsize, (u8*)bufcomp, (u8*)bufcrypt, 
            g_options.encryptpass, strlen((char*)g_options.encryptpass), 1))!=0)
        {   errprintf("crypt_block_blowfish() failed\n");
            return -1;
        }
        free(bufcomp);
        blkinfo->blkdata=bufcrypt;
        blkinfo->blkarsize=cryptsize;
        blkinfo->blkcryptalgo=ENCRYPT_BLOWFISH;
    }
    else
    {
        blkinfo->blkcryptalgo=ENCRYPT_NONE;
    }
    
    // calculates the final block checksum (block as it will be stored in the archive)
    blkinfo->blkarcsum=fletcher32((void*)blkinfo->blkdata, blkinfo->blkarsize);
    
    return 0;
}
int decompress_block_generic(struct s_blockinfo *blkinfo)
{
    u64 checkorigsize;
    char *bufcomp=NULL;
    int res;
    
    // allocate memory for uncompressed data
    if ((bufcomp=malloc(blkinfo->blkrealsize))==NULL)
    {   errprintf("malloc(%ld) failed: cannot allocate memory for compressed block\n", (long)blkinfo->blkrealsize);
        return -1;
    }
    
    // check the block checksum
    if (fletcher32((u8*)blkinfo->blkdata, blkinfo->blkarsize)!=(blkinfo->blkarcsum))
    {   errprintf("block is corrupt at blockoffset=%ld, blksize=%ld\n", (long)blkinfo->blkoffset, (long)blkinfo->blkrealsize);
        memset(bufcomp, 0, blkinfo->blkrealsize);
    }
    else // data not corrupted, decompresses the block
    {
        if ((blkinfo->blkcryptalgo!=ENCRYPT_NONE) && (g_options.encryptalgo!=ENCRYPT_BLOWFISH))
        {   msgprintf(MSG_DEBUG1, "this archive has been encrypted, you have to provide a password "
                "on the command line using option '-c'\n");
            return -1;
        }
        
        char *bufcrypt=NULL;
        u64 clearsize;
        if (blkinfo->blkcryptalgo==ENCRYPT_BLOWFISH)
        {
            if ((bufcrypt=malloc(blkinfo->blkrealsize+8))==NULL)
            {   errprintf("malloc(%ld) failed: out of memory\n", (long)blkinfo->blkrealsize+8);
                return -1;
            }
            if ((res=crypto_blowfish(blkinfo->blkarsize, &clearsize, (u8*)blkinfo->blkdata, (u8*)bufcrypt, 
                g_options.encryptpass, strlen((char*)g_options.encryptpass), 0))!=0)
            {   errprintf("crypt_block_blowfish() failed\n");
                return -1;
            }
            if (clearsize!=blkinfo->blkcompsize)
            {   errprintf("clearsize does not match blkcompsize: clearsize=%ld and blkcompsize=%ld\n", 
                    (long)clearsize, (long)blkinfo->blkcompsize);
                return -1;
            }
            free(blkinfo->blkdata);
            blkinfo->blkdata=bufcrypt;
        }
        
        switch (blkinfo->blkcompalgo)
        {
            case COMPRESS_NONE:
                memcpy(bufcomp, blkinfo->blkdata, blkinfo->blkarsize);
                res=0;
                break;
#ifdef OPTION_LZO_SUPPORT
            case COMPRESS_LZO:
                if ((res=uncompress_block_lzo(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0)
                {   errprintf("uncompress_block_lzo()=%d failed: finalsize=%ld and checkorigsize=%ld\n", 
                        res, (long)blkinfo->blkarsize, (long)checkorigsize);
                    memset(bufcomp, 0, blkinfo->blkrealsize);
                    // TODO: inc(error_counter);
                }
                break;
#endif // OPTION_LZO_SUPPORT
            case COMPRESS_GZIP:
                if ((res=uncompress_block_gzip(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0)
                {   errprintf("uncompress_block_gzip()=%d failed: finalsize=%ld and checkorigsize=%ld\n", 
                        res, (long)blkinfo->blkarsize, (long)checkorigsize);
                    memset(bufcomp, 0, blkinfo->blkrealsize);
                    // TODO: inc(error_counter);
                }
                break;
            case COMPRESS_BZIP2:
                if ((res=uncompress_block_bzip2(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0)
                {   errprintf("uncompress_block_bzip2()=%d failed: finalsize=%ld and checkorigsize=%ld\n", 
                        res, (long)blkinfo->blkarsize, (long)checkorigsize);
                    memset(bufcomp, 0, blkinfo->blkrealsize);
                    // TODO: inc(error_counter);
                }
                break;
#ifdef OPTION_LZMA_SUPPORT
            case COMPRESS_LZMA:
                if ((res=uncompress_block_lzma(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0)
                {   errprintf("uncompress_block_lzma()=%d failed: finalsize=%ld and checkorigsize=%ld\n", 
                        res, (long)blkinfo->blkarsize, (long)checkorigsize);
                    memset(bufcomp, 0, blkinfo->blkrealsize);
                    // TODO: inc(error_counter);
                }
                break;
#endif // OPTION_LZMA_SUPPORT
            default:
                errprintf("unsupported compression algorithm: %ld\n", (long)blkinfo->blkcompalgo);
                return -1;
        }
        free(blkinfo->blkdata); // free old buffer (with compressed data)
        blkinfo->blkdata=bufcomp; // pointer to new buffer with uncompressed data
    }
    
    return 0;
}
Ejemplo n.º 6
0
int archreader_read_block(carchreader *ai, cdico *in_blkdico, int in_skipblock, int *out_sumok, struct s_blockinfo *out_blkinfo)
{
    u32 arblockcsumorig;
    u32 arblockcsumcalc;
    u32 curblocksize; // data size
    u64 blockoffset; // offset of the block in the file
    u16 compalgo; // compression algo used
    u16 cryptalgo; // encryption algo used
    u32 finalsize; // compressed  block size
    u32 compsize;
    u8 *buffer;
    bool corrupt;
    
    assert(ai);
    assert(out_sumok);
    assert(in_blkdico);
    assert(out_blkinfo);
    
    // init
    memset(out_blkinfo, 0, sizeof(struct s_blockinfo));
    *out_sumok=-1;
    
    if (dico_get_u64(in_blkdico, 0, BLOCKHEADITEMKEY_BLOCKOFFSET, &blockoffset)!=0)
    {   msgprintf(3, "cannot get blockoffset from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_REALSIZE, &curblocksize)!=0 || curblocksize>FSA_MAX_BLKSIZE)
    {   msgprintf(3, "cannot get blocksize from block-header\n");
        return -1;
    }
    
    if (dico_get_u16(in_blkdico, 0, BLOCKHEADITEMKEY_COMPRESSALGO, &compalgo)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_COMPRESSALGO from block-header\n");
        return -1;
    }
    
    if (dico_get_u16(in_blkdico, 0, BLOCKHEADITEMKEY_ENCRYPTALGO, &cryptalgo)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_ENCRYPTALGO from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_ARSIZE, &finalsize)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_ARSIZE from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_COMPSIZE, &compsize)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_COMPSIZE from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_ARCSUM, &arblockcsumorig)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_ARCSUM from block-header\n");
        return -1;
    }
    
    if (in_skipblock==true) // the main thread does not need that block (block belongs to a filesys we want to skip)
    {
        if (lseek64(ai->archfd, (long)finalsize, SEEK_CUR)<0)
        {   sysprintf("cannot skip block (finalsize=%ld) failed\n", (long)finalsize);
            return -1;
        }
        return 0;
    }
    
    // ---- allocate memory
    if ((buffer=malloc(finalsize))==NULL)
    {   errprintf("cannot allocate block: malloc(%d) failed\n", finalsize);
        return FSAERR_ENOMEM;
    }
    
    if (read(ai->archfd, buffer, (long)finalsize)!=(long)finalsize)
    {   sysprintf("cannot read block (finalsize=%ld) failed\n", (long)finalsize);
        free(buffer);
        return -1;
    }
    
    // prepare blkinfo
    out_blkinfo->blkdata=(char*)buffer;
    out_blkinfo->blkrealsize=curblocksize;
    out_blkinfo->blkoffset=blockoffset;
    out_blkinfo->blkarcsum=arblockcsumorig;
    out_blkinfo->blkcompalgo=compalgo;
    out_blkinfo->blkcryptalgo=cryptalgo;
    out_blkinfo->blkarsize=finalsize;
    out_blkinfo->blkcompsize=compsize;
    
    // ---- checksum
    arblockcsumcalc=fletcher32(buffer, finalsize);
    corrupt=false;
    if (arblockcsumcalc!=arblockcsumorig) // bad checksum
    {
        errprintf("block is corrupt at offset=%ld, blksize=%ld\n", (long)blockoffset, (long)curblocksize);
        corrupt=!g_options.keepcorrupt;
    }
    if (corrupt) {
        free(out_blkinfo->blkdata);
        if ((out_blkinfo->blkdata=malloc(curblocksize))==NULL)
        {   errprintf("cannot allocate block: malloc(%d) failed\n", curblocksize);
            return FSAERR_ENOMEM;
        }
        memset(out_blkinfo->blkdata, 0, curblocksize);
        *out_sumok=false;
        // go to the beginning of the corrupted contents so that the next header is searched here
        if (lseek64(ai->archfd, -(long long)finalsize, SEEK_CUR)<0)
        {   errprintf("lseek64() failed\n");
        }
    }
    else // no corruption detected
    {
        *out_sumok=true;
    }
    
    return 0;
}
Ejemplo n.º 7
0
int archreader_read_dico(carchreader *ai, cdico *d)
{
    u16 size;
    u32 headerlen;
    u32 origsum;
    u32 newsum;
    u8 *buffer;
    u8 *bufpos;
    u16 temp16;
    u32 temp32;
    u8 section;
    u16 count;
    u8 type;
    u16 key;
    int i;
    
    assert(ai);
    assert(d);
    
    // header-len, header-data, header-checksum
    switch (ai->filefmtver)
    {
        case 1:
            if (archreader_read_data(ai, &temp16, sizeof(temp16))!=0)
            {   errprintf("imgdisk_read_data() failed\n");
                return OLDERR_FATAL;
            }
            headerlen=le16_to_cpu(temp16);
            break;
        case 2:
            if (archreader_read_data(ai, &temp32, sizeof(temp32))!=0)
            {   errprintf("imgdisk_read_data() failed\n");
                return OLDERR_FATAL;
            }
            headerlen=le32_to_cpu(temp32);
            break;
        default:
            errprintf("Fatal error: invalid file format version: ai->filefmtver=%d\n", ai->filefmtver);
            return OLDERR_FATAL;
    }
    
    bufpos=buffer=malloc(headerlen);
    if (!buffer)
    {   errprintf("cannot allocate memory for header\n");
        return FSAERR_ENOMEM;
    }
    
    if (archreader_read_data(ai, buffer, headerlen)!=0)
    {   errprintf("cannot read header data\n");
        free(buffer);
        return OLDERR_FATAL;
    }
    
    if (archreader_read_data(ai, &temp32, sizeof(temp32))!=0)
    {   errprintf("cannot read header checksum\n");
        free(buffer);
        return OLDERR_FATAL;
    }
    origsum=le32_to_cpu(temp32);
    
    // check header-data integrity using checksum    
    newsum=fletcher32(buffer, headerlen);
    
    if (newsum!=origsum)
    {   errprintf("bad checksum for header\n");
        free(buffer);
        return OLDERR_MINOR; // header corrupt --> skip file
    }
    
    // read count from buffer
    memcpy(&temp16, bufpos, sizeof(temp16));
    bufpos+=sizeof(temp16);
    count=le16_to_cpu(temp16);
    
    // read items
    for (i=0; i < count; i++)
    {
        // a. read type from buffer
        memcpy(&type, bufpos, sizeof(type));
        bufpos+=sizeof(section);
        
        // b. read section from buffer
        memcpy(&section, bufpos, sizeof(section));
        bufpos+=sizeof(section);
        
        // c. read key from buffer
        memcpy(&temp16, bufpos, sizeof(temp16));
        bufpos+=sizeof(temp16);
        key=le16_to_cpu(temp16);
        
        // d. read sizeof(data)
        memcpy(&temp16, bufpos, sizeof(temp16));
        bufpos+=sizeof(temp16);
        size=le16_to_cpu(temp16);
        
        // e. add item to dico
        if (dico_add_generic(d, section, key, bufpos, size, type)!=0)
            return OLDERR_FATAL;
        bufpos+=size;
    }
    
    free(buffer);
    return FSAERR_SUCCESS;
}