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 + -
显示快捷键?