/* af_open_with is the real open routine. * It opens a particular file with a particular vnode implementation. */ AFFILE *af_open_with(const char *url,int flags,int mode, struct af_vnode *v) { /* Alloate the space for the AFFILE structure */ AFFILE *af = (AFFILE *)calloc(sizeof(AFFILE),1); af_crypto_allocate(af); #ifdef HAVE_PTHREAD pthread_rwlock_init(&af->rwlock); AF_WRLOCK(af); #endif af->v = v; af->version = 2; af->openflags = flags | O_BINARY; // make sure that we ask for binray af->openmode = mode; af->image_sectorsize = 512; // default size af->error_reporter = warnx; af->badflag = (unsigned char *)malloc(af->image_sectorsize); /* Decode URL */ af_parse_url(url,&af->protocol,&af->hostname,&af->username,&af->password, &af->port,&af->fname); /* A null passphrase is the same as no passphrase*/ if(af->password && af->password[0]==0){ free(af->password); af->password=0; } /* If no password was set and the AFFLIB_PASSPHRASE environment variable is set, use that */ if(af->password==0 && getenv(AFFLIB_PASSPHRASE)){ af->password = strdup(getenv(AFFLIB_PASSPHRASE)); } /* If no password is set and its in a file, get it there */ if(af->password==0 && getenv(AFFLIB_PASSPHRASE_FILE)){ int fd = open(AFFLIB_PASSPHRASE_FILE,O_RDONLY,0); if(fd>0){ struct stat sb; if(fstat(fd,&sb)==0){ af->password = (char *)malloc(sb.st_size); int r = read(fd,af->password,sb.st_size); if(r!=sb.st_size){ free(af->password); af->password=0; // couldn't read it } close(fd); } } } /* If no password is set and its in a file, get it there */ if(af->password==0 && getenv(AFFLIB_PASSPHRASE_FD)){ int fd = atoi(AFFLIB_PASSPHRASE_FD); af->password = (char *)malloc(1); int buflen = 0; int rlen = 0; char mybuf[1024]; while((rlen=read(fd,mybuf,sizeof(mybuf)))>0){ af->password = (char *)realloc(af->password,buflen+rlen+1); memcpy(af->password+buflen,mybuf,rlen); buflen += rlen; af->password[buflen] = '\000'; } } /* TK: If no password was set and the AFFLIB_ASK_PASS is set, ask for a passphrase */ /* Note things for hard files */ af->exists = (access(af->fname,R_OK) == 0); // does the file exist? /* Right now just set up the cache by hand */ const char *cache_pages = getenv(AFFLIB_CACHE_PAGES); if(cache_pages) af->num_pbufs = atoi(cache_pages); if(af->num_pbufs<1) af->num_pbufs = AFFLIB_CACHE_PAGES_DEFAULT; // default valuen af->pbcache = (struct aff_pagebuf *)calloc(af->num_pbufs,sizeof(struct aff_pagebuf)); if(af->pbcache==0){ // if can't allocate the full amount af->num_pbufs = 2; // try a significantly smaller cache af->pbcache = (struct aff_pagebuf *)calloc(af->num_pbufs,sizeof(struct aff_pagebuf)); } if(flags & AF_HALF_OPEN) return af; // for low-level tools /* Try opening it! */ if((*af->v->open)(af)){ strlcpy(af_error_str,af->error_str,sizeof(af_error_str)); // make a copy of the error string af_deallocate(af); return 0; } /* If there is no AFFKEY and the file is read-only, don't use a password */ if(af->password && (af_get_seg(af,AF_AFFKEY,0,0,0)!=0) && ((af->openflags & O_ACCMODE)==O_RDONLY)){ af_sanitize_password(af); } /* Set up the encryption if requested and if this support metadata */ if(AF_SEALING_VNODE(af) && ((flags & AF_NO_CRYPTO)==0)){ bool can_decrypt = false; if(af->password){ struct af_vnode_info vni; memset(&vni,0,sizeof(vni)); if((*af->v->vstat)(af,&vni)==0 && vni.supports_metadata){ int r = 0; if(af_get_seg(af,AF_AFFKEY,0,0,0)!=0){ // it does not have a password r = af_establish_aes_passphrase(af,af->password); } if(r==0){ r = af_use_aes_passphrase(af,af->password); if(r==0) { can_decrypt = true; } else { (*af->error_reporter)("af_open: invalid passphrase: '%s'",af->password); } } af_sanitize_password(af); } } /* Try public key... */ if(can_decrypt==false){ const char *kf = getenv(AFFLIB_DECRYPTING_PRIVATE_KEYFILE); if(kf){ af_set_unseal_keyfile(af,kf); } } } af_read_sizes(af); // set up the metadata if(af_trace) fprintf(af_trace,"af_open_with(%s,%o,%o,%s)\n",url,flags,mode,v->name); return af; }
int aestest() { unsigned char keyblock[32]; /* Make a key; doesn't need to be a good key; make it 256 bits */ for(int i=0;i<32;i++){ keyblock[i] = i; } AFFILE *af = af_open("crypto.aff",O_CREAT|O_RDWR|O_TRUNC,0666); if(!af) err(1,"af_open"); if(af_set_aes_key(af,keyblock,256)) err(1,"af_set_aes_key"); af_set_pagesize(af,65536); /* Now, let's write some data of various sizes */ u_char test[1024],buf[1024],rbuf[1024]; size_t buflen = sizeof(buf); make_test_seg(test,0); for(u_int len=0;len<=strlen((const char *)test);len++){ if(af_update_seg(af,"page0",0,test,len)) err(1,"af_update_seg len=%d",len); /* Now try to read the segment */ memset(buf,0,sizeof(buf)); buflen = sizeof(buf); if(af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen)){ err(1,"Could not read encrypted segment with length %d.\n",len); } if(buflen!=len){ printf("size of returned segment = %zd ",buflen); printf("(should be %d) \n",len); exit(0); } if(memcmp(buf,test,len)!=0){ printf("does not match\n"); printf(" wanted: %s\n",test); printf(" got: %s\n",buf); exit(0); } } if(af_close(af)) err(1,"af_close"); /* Now re-open the file, do not set the encryption key, and see if we can read it */ int r; memset(buf,0,sizeof(buf)); af = af_open("crypto.aff",O_RDONLY,0666); buflen = sizeof(buf); r = af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen); if(r!=-1) { errx(1,"Error; attempt to read segment 'encrypted' succeded. It should have failed."); } /* Try to read 'encrypted/aes' */ r = af_get_seg(af,"encrypted/aes",0,(unsigned char *)buf,&buflen); if(memcmp(buf,test,buflen)==0){ errx(1,"Error: segment encrypted/aes wasn't actually encrypted."); } af_close(af); /* Now set the correct encryption key and see if we can read it */ af = af_open("crypto.aff",O_RDONLY,0666); if(af_set_aes_key(af,keyblock,256)) err(1,"af_set_aes_key"); buflen = sizeof(buf); memset(buf,0,sizeof(buf)); r = af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen); if(buflen != strlen((const char *)test)){ errx(1,"Error: Could not read encrypted segment after re-opening file"); } if(memcmp(buf,test,buflen)!=0) errx(1,"Error: Re-read of file produces wrong data."); printf("encrypted data read and decrypted: '%s'\n",buf); /* Try to read a segment that doesn't eixst */ buflen = 0; if(af_get_seg(af,"encrypted2",0,0,&buflen)==0){ errx(1,"Error: Attempt to get size of non-existant segment 'encrypted2' got %zd\n",buflen); } af_close(af); /* Now set the wrong encryption key and see if we can read it */ memset(buf,0,sizeof(buf)); af = af_open("crypto.aff",O_RDONLY,0666); keyblock[3] = 42; if(af_set_aes_key(af,keyblock,256)) err(1,"af_set_aes_key"); buflen = sizeof(buf); r = af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen); if(memcmp(buf,test,buflen)==0) errx(1,"Error: Setting wrong key still produces correct data."); af_close(af); printf("Basic crypto checks. Now check passphrase....\n"); /* Write the data with a passphrase and try to read it back */ af = af_open("crypto_pass.aff",O_CREAT|O_RDWR|O_TRUNC,0666); if(!af) err(1,"af_open 3"); af_set_pagesize(af,65536); if(af_establish_aes_passphrase(af,"yummy")) err(1,"af_establish_aes_passphrase"); if(af_use_aes_passphrase(af,"yummy")) err(1,"af_use_aes_passphrase"); if(af_update_seg(af,"page0",0,(const u_char *)test,strlen((const char *)test))) err(1,"af_update_seg failed at 3"); if(af_close(af)) err(1,"af_close at 3"); /* Now try to read it back */ memset(rbuf,0,sizeof(rbuf)); size_t rbuflen = sizeof(rbuf); af = af_open("crypto_pass.aff",O_RDONLY,0666); if(!af) err(1,"af_open 4"); if(af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen)==0){ errx(1,"af_get_seg should have failed and didn't"); } if(af_use_aes_passphrase(af,"yummy")) err(1,"af_set_passphrase 2"); rbuflen=sizeof(rbuf); if(af_get_seg(af,"page0",0,(unsigned char *)rbuf,&rbuflen)){ errx(1,"af_get_seg failed"); } if(rbuflen!=strlen((const char *)test)) errx(1,"Reading encrypted data returned wrong size"); if(memcmp(rbuf,test,rbuflen)!=0) errx(1,"Error: wrong data"); printf("encrypted data read with passphrase 'yummy': %s\n",rbuf); af_close(af); /* Try to change the passphrase */ af = af_open("crypto_pass.aff",O_RDWR,0666); if(!af) err(1,"af_open 5"); if(af_change_aes_passphrase(af,"yummy","dummy")) err(1,"could not change passphrase"); af_close(af); /* Try to read with new passphrase */ af = af_open("crypto_pass.aff",O_RDONLY,0666); if(!af) err(1,"af_open 5"); memset(rbuf,0,sizeof(rbuf)); rbuflen = sizeof(rbuf); if(af_use_aes_passphrase(af,"dummy")) err(1,"af_set_passphrase 2"); rbuflen=sizeof(rbuf); if(af_get_seg(af,"page0",0,(unsigned char *)rbuf,&rbuflen)){ errx(1,"af_get_seg failed"); } if(rbuflen!=strlen((const char *)test)) errx(1,"Reading encrypted with new passphrase data returned wrong size"); if(memcmp(rbuf,test,rbuflen)!=0) errx(1,"Error: wrong data"); printf("encrypted data read with new passphrase 'dummy': %s\n",rbuf); af_close(af); exit(0); /* Now try to read with the wrong passphrase */ af = af_open("crypto.aff",O_RDONLY,0666); if(af_use_aes_passphrase(af,"yummy2")) err(1,"af_set_passphrase 3"); buflen=sizeof(buf); memset(buf,0,sizeof(buf)); if(af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen)){ printf("Couldn't get data with wrong passphrase (that's good)\n"); } printf("data read with wrong passphrase: %s\n",buf); if(buflen>0 && memcmp(buf,test,buflen)==0){ errx(1,"Error: data fetched with wrong passphrase was not scrambled."); } af_close(af); exit(0); }