armour.c

来自「Cryptmount是对Linux系统下的文件系统以及用户设备、文档等进行加密的」· C语言 代码 · 共 1,528 行 · 第 1/3 页

C
1,528
字号
    keyinfo.cipheralg = "CAST5-CFB";    keyinfo.digestalg = "ripemd160";    CM_ASSERT_EQUAL(ERR_NOERROR,        kmgcry_get_algos(&keyinfo, &cipher, &mode, &digest));    CM_ASSERT_EQUAL(GCRY_CIPHER_CAST5, cipher);    CM_ASSERT_EQUAL(GCRY_CIPHER_MODE_CFB, mode);    CM_ASSERT_EQUAL(GCRY_MD_RMD160, digest);    CM_TEST_OK();}#  endif    /* TESTING */int kmgcry_initcipher(int cipher, int ciphermode, int digest,            const unsigned char *salt, const char *pass, size_t passlen,            gcry_cipher_hd_t *hd){   gcry_md_hd_t md_hand;    size_t ckeysz,cblksz,kpos,ivpos,pos,mdlen;    unsigned char *ckey=NULL,*civ=NULL,*buff;    int eflag=ERR_BADALGORITHM;    if (gcry_cipher_open(hd, cipher, ciphermode, 0) != 0) {        fprintf(stderr, "cannot open libgcrypt cipher[%d,%d]\n",                cipher, ciphermode);        goto bail_out;    }    (void)gcry_cipher_algo_info(cipher, GCRYCTL_GET_KEYLEN, NULL, &ckeysz);    ckey = (unsigned char*)sec_realloc(ckey, ckeysz);    gcry_cipher_algo_info(cipher, GCRYCTL_GET_BLKLEN, NULL, &cblksz);    civ = (unsigned char*)sec_realloc(civ, cblksz);    /* generate cipher key & iv by hashing password: */    kpos = ivpos = 0;    if (gcry_md_open(&md_hand, digest, 0) != 0) {        fprintf(stderr, "cannot open libgcrypt digest[%d]\n", digest);        goto bail_out;    }    mdlen = gcry_md_get_algo_dlen(digest);    do {        gcry_md_reset(md_hand);        gcry_md_write(md_hand, (const void*)salt, (size_t)kmgcry_saltlen);        gcry_md_write(md_hand, (const void*)pass, passlen);        if (kpos > 0) {            gcry_md_write(md_hand, (const void*)ckey, kpos); }        if (ivpos > 0) {            gcry_md_write(md_hand, (const void*)civ, ivpos); }        buff = gcry_md_read(md_hand, digest);        pos = 0;        while (kpos < ckeysz && pos < mdlen) {            ckey[kpos++] = buff[pos++]; }        while (ivpos < cblksz && pos < mdlen) {            civ[ivpos++] = buff[pos++]; }    } while (kpos < ckeysz || ivpos < cblksz);    gcry_md_close(md_hand);    /* setup cipher initial state: */    if (gcry_cipher_setkey(*hd, (void*)ckey, ckeysz) != 0      || gcry_cipher_setiv(*hd, (void*)civ, cblksz) != 0) {        fprintf(stderr, "failed to setup libgcrypt cipher iv[%d,%d]\n",                (int)ckeysz, (int)cblksz);        goto bail_out;    }    sec_free(ckey);    sec_free(civ);    eflag = ERR_NOERROR;  bail_out:    return eflag;}int kmgcry_init_algs(){    /* nothing needed */    return 0;}int kmgcry_free_algs(){    /* nothing needed */    return 0;}void kmgcry_mk_default(keyinfo_t *keyinfo){    if (keyinfo == NULL) return;    if (keyinfo->digestalg == NULL) {        keyinfo->digestalg = cm_strdup("md5");    }    if (keyinfo->cipheralg == NULL) {        keyinfo->cipheralg = cm_strdup("blowfish");    }}int kmgcry_is_compat(const keyinfo_t *keyinfo){    /* be prepared to act as default keymanager if format is unspecified: */    return (keyinfo->format == NULL || strcmp(keyinfo->format, "libgcrypt") == 0);}static int kmgcry_get_key(const char *ident, const keyinfo_t *keyinfo,            unsigned char **key, int *keylen, FILE *fp_key)    /* extract key from unencrypted (plain) file */{   gcry_cipher_hd_t chd;    char *passwd=NULL;    unsigned char salt[kmgcry_saltlen];    enum { BUFFSZ=512 };    unsigned char buff[BUFFSZ],*bptr;    size_t cblksz;    uint32_t chksum,*kptr;    int cnt,cipher,ciphermode,digest,eflag=ERR_NOERROR;    *key = NULL; *keylen = 0;    eflag = kmgcry_get_algos(keyinfo, &cipher, &ciphermode, &digest);    if (eflag != ERR_NOERROR) goto bail_out;    gcry_cipher_algo_info(cipher, GCRYCTL_GET_BLKLEN, NULL, &cblksz);#ifdef TESTING    passwd = (char*)malloc((size_t)BUFFSZ);    strncpy(passwd, (argpassword[1] != NULL ? argpassword[1] : ""),            BUFFSZ);#else    if (km_get_passwd(ident, &passwd, 0, 0) != ERR_NOERROR) goto bail_out;#endif    /* read key header: */    fread((void*)buff, (size_t)1, kmgcry_maglen, fp_key);    if (strncmp((const char*)buff, kmgrcy_magstr, kmgcry_maglen) != 0) {        fprintf(stderr, "bad keyfile format\n");        eflag = ERR_BADFILE;        goto bail_out;    }    fread((void*)buff, (size_t)1, (size_t)1, fp_key);    if (buff[0] != '\0') {        fprintf(stderr, "bad keyfile version [%d]\n", (int)buff[0]);        eflag = ERR_BADFILE;        goto bail_out;    }    fread((void*)buff, (size_t)4, (size_t)1, fp_key);    if (buff[0] != (cblksz & 0xff) || buff[1] != ((cblksz & 0xff00) >> 8)) {        fprintf(stderr, "mismatched cipher block size\n");        eflag = ERR_BADFILE;        goto bail_out;    }    *keylen = (int)buff[2] | ((int)buff[3] << 8);    /* read salt from keyfile: */    fread((void*)salt, (size_t)1, sizeof(salt), fp_key);    /* read encrypted key from keyfile: */    kmgcry_initcipher(cipher, ciphermode, digest,                    salt, passwd, strlen(passwd), &chd);    cnt = ((*keylen + 8 + cblksz - 1) / cblksz);    bptr = buff;    while (cnt--) {        fread((void*)bptr, cblksz, (size_t)1, fp_key);        gcry_cipher_decrypt(chd, (void*)bptr, cblksz, NULL, 0);        bptr += cblksz;    }    gcry_cipher_close(chd);    /* verify checksum: */    cnt = (*keylen + sizeof(chksum) - 1) / sizeof(chksum);    chksum = 0;    kptr = (uint32_t*)buff;    while (cnt--) {        chksum ^= *kptr;        ++kptr;    }    if (chksum != *kptr) {        fprintf(stderr, "checksum mismatch in keyfile (%x != %x)\n",            chksum, *kptr);        eflag = ERR_BADFILE;    }    if (keyinfo->maxlen > 0 && *keylen > keyinfo->maxlen) {        *keylen = keyinfo->maxlen;    }    *key = (unsigned char*)sec_realloc((void*)*key, (size_t)*keylen);    memcpy(*key, buff, *keylen);    if (ferror(fp_key) != 0) {        fprintf(stderr, _("key-extraction failed for \"%s\"\n"),                keyinfo->filename);        eflag = ERR_BADDECRYPT;    }  bail_out:    return eflag;}static int kmgcry_put_key(const char *ident, const keyinfo_t *keyinfo,            const unsigned char *key, const int keylen, FILE *fp_key)    /* store key in unencrypted (plain) file */{   gcry_cipher_hd_t chd;    char *passwd=NULL;    unsigned char salt[kmgcry_saltlen],*buff=NULL,*bptr;    size_t idx,buffsz,cblksz;    uint32_t chksum,*kptr;    int cnt,cipher,ciphermode,digest,eflag=ERR_NOERROR;    eflag = kmgcry_get_algos(keyinfo, &cipher, &ciphermode, &digest);    if (eflag != ERR_NOERROR) goto bail_out;    gcry_cipher_algo_info(cipher, GCRYCTL_GET_BLKLEN, NULL, &cblksz);    buffsz = cblksz * ((keylen + 8 + cblksz - 1) / cblksz);    buff = (unsigned char*)sec_realloc(buff, buffsz);#ifdef TESTING    passwd = sec_realloc((void*)passwd, (size_t)1024);    strncpy(passwd, (argpassword[1] != NULL ? argpassword[1] : ""),            1024);#else    if (km_get_passwd(ident, &passwd, 1, 1) != ERR_NOERROR) goto bail_out;#endif    /* write key header: */    fwrite((const void*)kmgrcy_magstr, (size_t)1, kmgcry_maglen, fp_key);    fwrite((const void*)&kmgcry_version, (size_t)1, (size_t)1, fp_key);    buff[0] = (cblksz & 0xff); buff[1] = (cblksz & 0xff00) >> 8;    buff[2] = (keylen & 0xff); buff[3] = (keylen & 0xff00) >> 8;    fwrite((const void*)buff, (size_t)4, (size_t)1, fp_key);    /* generate salt & record in keyfile: */    get_randkey(salt, sizeof(salt));    fwrite((const void*)salt, (size_t)1, sizeof(salt), fp_key);    /* copy key & generate crude checksum: */    memset(buff, 0, buffsz);    memcpy(buff, key, keylen);    cnt = (keylen + sizeof(chksum) - 1) / sizeof(chksum);    chksum = 0;    kptr = (uint32_t*)buff;    for (idx=0; idx<(size_t)cnt; ++idx) {        chksum ^= *kptr;        ++kptr;    }    *kptr = chksum;     /* invariant with respect to byte-ordering */    idx = (idx + 1) * sizeof(chksum);    if (idx < buffsz) {        get_randkey((buff + idx), (buffsz - idx));    }    /* write encrypted key into keyfile: */    kmgcry_initcipher(cipher, ciphermode, digest,                    salt, passwd, strlen(passwd), &chd);    cnt = buffsz / cblksz;    bptr = buff;    while (cnt--) {        gcry_cipher_encrypt(chd, (void*)bptr, cblksz, NULL, 0);        fwrite((const void*)bptr, cblksz, (size_t)1, fp_key);        bptr += cblksz;    }    gcry_cipher_close(chd);  bail_out:    if (buff != NULL) sec_free(buff);    if (passwd != NULL) sec_free(passwd);    return eflag;}void *kmgcry_md_prepare(){   gcry_md_hd_t *handle;    handle = (gcry_md_hd_t*)malloc(sizeof(gcry_md_hd_t));    (void)gcry_md_open(handle, GCRY_MD_SHA1, 0);    return (void*)handle;}void kmgcry_md_block(void *state, unsigned char *buff, unsigned len){   gcry_md_hd_t *handle=(gcry_md_hd_t*)state;    gcry_md_write(*handle, (const void*)buff, (size_t)len);}void kmgcry_md_final(void *state, unsigned char **mdval, unsigned *mdlen){   gcry_md_hd_t *handle=(gcry_md_hd_t*)state;    unsigned char *buff;    int algo;    gcry_md_final(*handle);    algo = gcry_md_get_algo(*handle);    *mdlen = gcry_md_get_algo_dlen(algo);    buff = gcry_md_read(*handle, algo);    *mdval = (unsigned char*)malloc((size_t)*mdlen);    memcpy((void*)*mdval, (const void*)buff, (size_t)*mdlen);}void kmgcry_md_release(void *state){   gcry_md_hd_t *handle=(gcry_md_hd_t*)state;    gcry_md_close(*handle);    free((void*)handle);}#  ifdef TESTINGint kmgcry_test_hash(){   void *mdcontext;    unsigned char *mdval=NULL;    unsigned mdlen,i,q;    const char *str="noisy\n";    const char *hash="7c1c9261fa774475ec1c0d887eaf00c19b0eb218";    CM_TEST_START("libgcrypt hashing");    mdcontext = kmgcry_md_prepare();    CM_ASSERT_DIFFERENT(NULL, mdcontext);    kmgcry_md_block(mdcontext, (unsigned char*)str, strlen(str));    kmgcry_md_final(mdcontext, &mdval, &mdlen);    CM_ASSERT_DIFFERENT(NULL, mdval);    CM_ASSERT_EQUAL(strlen(hash)/2, mdlen);    for (i=0; i<mdlen; ++i) {        sscanf(hash+2*i, "%2x", &q);        CM_ASSERT_EQUAL(q, mdval[i]);    }    kmgcry_md_release(mdcontext);    CM_TEST_OK();}#  endif    /* TESTING */#endif  /* HAVE_LIBGCRYPT *//* *  ==== raw key-management routines ==== */int kmraw_init_algs(){    return 0;}int kmraw_free_algs(){    return 0;}void kmraw_mk_default(keyinfo_t *keyinfo){    if (keyinfo == NULL) return;    if (keyinfo->digestalg == NULL) {        keyinfo->digestalg = cm_strdup("none");    }    if (keyinfo->cipheralg == NULL) {        keyinfo->cipheralg = cm_strdup("none");    }}int kmraw_is_compat(const keyinfo_t *keyinfo){    return (keyinfo != NULL && strcmp(keyinfo->cipheralg, "none") == 0);}static int kmraw_get_key(const char *ident, const keyinfo_t *keyinfo,            unsigned char **key, int *keylen, FILE *fp_key)    /* extract key from unencrypted (plain) file */{   enum { BUFFSZ=512 };    char buff[BUFFSZ];    int len,lmt,eflag=ERR_NOERROR;    *key = NULL; *keylen = 0;    if (fp_key == NULL) {        eflag = ERR_BADFILE;        goto bail_out;    }    /* read data directly from keyfile: */    for (;;) {        lmt = (keyinfo->maxlen > 0 && (*keylen + BUFFSZ) > keyinfo->maxlen                ? keyinfo->maxlen - *keylen : BUFFSZ);        len = fread((void*)buff, (size_t)1, (size_t)lmt, fp_key);        if (len <= 0) break;        /* copy new block of data onto end of current key: */        *key = (unsigned char*)sec_realloc((void*)*key, (size_t)(*keylen+len));        memcpy((void*)(*key + *keylen), (const void*)buff, len);        *keylen += len;    }    if (ferror(fp_key) != 0) {        fprintf(stderr, _("key-extraction failed for \"%s\"\n"),                keyinfo->filename);        eflag = ERR_BADDECRYPT;    }  bail_out:    return eflag;}static int kmraw_put_key(const char *ident, const keyinfo_t *keyinfo,            const unsigned char *key, const int keylen, FILE *fp_key)    /* store key in unencrypted (plain) file */{   int eflag=ERR_NOERROR;    /* write data directly into keyfile: */    if (fwrite((const void*)key, (size_t)keylen, (size_t)1, fp_key) != 1      || ferror(fp_key) != 0) {        fprintf(stderr, _("key-writing failed for \"%s\"\n"),                keyinfo->filename);        eflag = ERR_BADENCRYPT;    }    return eflag;}void *kmraw_md_prepare(){   unsigned long *mdcontext;    /* you're in trouble if this ends up being your default hashing alg */    mdcontext = (unsigned long*)malloc(sizeof(unsigned long));    *mdcontext = 0xc0895ca3;    *mdcontext = (*mdcontext << 16) ^ 0x306a5498;    return (void*)mdcontext;}void kmraw_md_block(void *state, unsigned char *buff, unsigned len){   unsigned long *mdcontext=(unsigned long*)state;    while (len > 0) {        *mdcontext = (*mdcontext << 1) ^ ((*mdcontext >> 5) & 1);        *mdcontext ^= (unsigned long)*buff;        ++buff; --len;    }}void kmraw_md_final(void *state, unsigned char **mdval, unsigned *mdlen){    *mdval = (unsigned char*)malloc(sizeof(unsigned long));    memcpy((void*)*mdval, (const void*)state, sizeof(unsigned long));    *mdlen = sizeof(unsigned long);}void kmraw_md_release(void *state){    free(state);}/* *  ==== abstract key-management interfaces ==== *//* This table contains abstract interfaces to cryptographic functions.   Early entries in the list represent good quality encryption functions.   The list is terminated by an entry whose .ident field is NULL */static keymanager_t keymgrs[] = {#if HAVE_OPENSSL    { "openssl", 0,     kmssl_init_algs, kmssl_free_algs,                        kmssl_mk_default, kmssl_is_compat,                        kmssl_get_key, kmssl_put_key,                        kmssl_md_prepare, kmssl_md_block,                        kmssl_md_final, kmssl_md_release },#endif#if HAVE_LIBGCRYPT    { "libgcrypt", 0,   kmgcry_init_algs, kmgcry_free_algs,                        kmgcry_mk_default, kmgcry_is_compat,                        kmgcry_get_key, kmgcry_put_key,                        kmgcry_md_prepare, kmgcry_md_block,                        kmgcry_md_final, kmgcry_md_release },#endif    { "raw", 0,         kmraw_init_algs, kmraw_free_algs,                        kmraw_mk_default, kmraw_is_compat,                        kmraw_get_key, kmraw_put_key,                        kmraw_md_prepare, kmraw_md_block,                        kmraw_md_final, kmraw_md_release },

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?