| 12 | | #include <openpgpsdk/armour.h> |
|---|
| 13 | | #include "openpgpsdk/keyring.h" |
|---|
| 14 | | #include "openpgpsdk/packet.h" |
|---|
| 15 | | #include "openpgpsdk/packet-parse.h" |
|---|
| 16 | | #include "openpgpsdk/util.h" |
|---|
| 17 | | #include "openpgpsdk/std_print.h" |
|---|
| 18 | | |
|---|
| 19 | | /* |
|---|
| 20 | | These include files are needed by callback. |
|---|
| 21 | | To be removed when callback gets added to main body of code |
|---|
| 22 | | */ |
|---|
| 23 | | #include "../src/advanced/parse_local.h" |
|---|
| 24 | | #include "../src/advanced/keyring_local.h" |
|---|
| 25 | | |
|---|
| 26 | | #define MAXBUF 128 |
|---|
| 27 | | static char secring[MAXBUF+1]; |
|---|
| 28 | | static char dir[MAXBUF+1]; |
|---|
| 29 | | static char keydetails[MAXBUF+1]; |
|---|
| 30 | | static ops_keyring_t keyring; |
|---|
| 31 | | static char *filename_rsa_noarmour_nopassphrase="rsa_noarmour_nopassphrase.txt"; |
|---|
| 32 | | static char *filename_rsa_armour_nopassphrase="rsa_armour_nopassphrase.txt"; |
|---|
| 33 | | static char *filename_rsa_noarmour_passphrase="rsa_noarmour_passphrase.txt"; |
|---|
| 34 | | static char *filename_rsa_armour_passphrase="rsa_armour_passphrase.txt"; |
|---|
| 35 | | static char *nopassphrase=""; |
|---|
| 36 | | static char *passphrase="hello"; |
|---|
| 37 | | static char *current_passphrase=NULL; |
|---|
| 38 | | |
|---|
| 39 | | static char* text; |
|---|
| 40 | | |
|---|
| 41 | | static char *create_testtext(const char *filename) |
|---|
| 42 | | { |
|---|
| 43 | | static char buffer[MAXBUF+1]; |
|---|
| 44 | | snprintf(buffer,MAXBUF,"Hello world : %s/%s\n", dir, filename); |
|---|
| 45 | | return &buffer[0]; |
|---|
| 46 | | } |
|---|
| 47 | | |
|---|
| 48 | | static int create_testfile(const char *name) |
|---|
| 49 | | { |
|---|
| 50 | | char filename[MAXBUF+1]; |
|---|
| 51 | | char buffer[MAXBUF+1]; |
|---|
| 52 | | |
|---|
| 53 | | int fd=0; |
|---|
| 54 | | snprintf(filename,MAXBUF,"%s/%s",dir,name); |
|---|
| 55 | | if ((fd=open(filename,O_WRONLY| O_CREAT | O_EXCL, 0600))<0) |
|---|
| 56 | | return 0; |
|---|
| 57 | | |
|---|
| 58 | | snprintf(buffer,MAXBUF,create_testtext(name)); |
|---|
| 59 | | write(fd,buffer,strlen(buffer)); |
|---|
| 60 | | close(fd); |
|---|
| 61 | | return 1; |
|---|
| 62 | | } |
|---|
| 63 | | |
|---|
| 64 | | static ops_parse_cb_return_t |
|---|
| 65 | | callback(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) |
|---|
| 66 | | { |
|---|
| 67 | | ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; |
|---|
| 68 | | static ops_boolean_t skipping; |
|---|
| 69 | | static const ops_key_data_t *decrypter; |
|---|
| 70 | | const ops_key_data_t *keydata=NULL; |
|---|
| 71 | | const ops_secret_key_t *secret; |
|---|
| 72 | | |
|---|
| 73 | | OPS_USED(cbinfo); |
|---|
| 74 | | |
|---|
| 75 | | // ops_print_packet(content_); |
|---|
| 76 | | |
|---|
| 77 | | if(content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping) |
|---|
| 78 | | { |
|---|
| 79 | | puts("...end of skip"); |
|---|
| 80 | | skipping=ops_false; |
|---|
| 81 | | } |
|---|
| 82 | | |
|---|
| 83 | | switch(content_->tag) |
|---|
| 84 | | { |
|---|
| 85 | | case OPS_PTAG_CT_UNARMOURED_TEXT: |
|---|
| 86 | | printf("OPS_PTAG_CT_UNARMOURED_TEXT\n"); |
|---|
| 87 | | if(!skipping) |
|---|
| 88 | | { |
|---|
| 89 | | puts("Skipping..."); |
|---|
| 90 | | skipping=ops_true; |
|---|
| 91 | | } |
|---|
| 92 | | fwrite(content->unarmoured_text.data,1, |
|---|
| 93 | | content->unarmoured_text.length,stdout); |
|---|
| 94 | | break; |
|---|
| 95 | | |
|---|
| 96 | | case OPS_PTAG_CT_PK_SESSION_KEY: |
|---|
| 97 | | // printf ("OPS_PTAG_CT_PK_SESSION_KEY\n"); |
|---|
| 98 | | if(decrypter) |
|---|
| 99 | | break; |
|---|
| 100 | | |
|---|
| 101 | | decrypter=ops_keyring_find_key_by_id(&keyring, |
|---|
| 102 | | content->pk_session_key.key_id); |
|---|
| 103 | | if(!decrypter) |
|---|
| 104 | | break; |
|---|
| 105 | | break; |
|---|
| 106 | | |
|---|
| 107 | | case OPS_PARSER_CMD_GET_SECRET_KEY: |
|---|
| 108 | | keydata=ops_keyring_find_key_by_id(&keyring,content->get_secret_key.pk_session_key->key_id); |
|---|
| 109 | | if (!keydata || !ops_key_is_secret(keydata)) |
|---|
| 110 | | return 0; |
|---|
| 111 | | |
|---|
| 112 | | // ops_set_secret_key(content,keydata); |
|---|
| 113 | | |
|---|
| 114 | | // Do we need the passphrase and not have it? If so, get it |
|---|
| 115 | | ops_parser_content_t pc; |
|---|
| 116 | | char *passphrase; |
|---|
| 117 | | memset(&pc,'\0',sizeof pc); |
|---|
| 118 | | passphrase=NULL; |
|---|
| 119 | | pc.content.secret_key_passphrase.passphrase=&passphrase; |
|---|
| 120 | | pc.content.secret_key_passphrase.secret_key=&(keydata->key.skey); |
|---|
| 121 | | |
|---|
| 122 | | /* Ugh. Need to duplicate this macro here to get the passphrase |
|---|
| 123 | | Duplication to be removed when the callback gets moved to main code. |
|---|
| 124 | | Can we make this inline code rather than a macro? |
|---|
| 125 | | */ |
|---|
| 126 | | #define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0) |
|---|
| 127 | | CB(cbinfo,OPS_PARSER_CMD_GET_SK_PASSPHRASE,&pc); |
|---|
| 128 | | |
|---|
| 129 | | /* now get the key from the data */ |
|---|
| 130 | | secret=ops_get_secret_key_from_data(keydata); |
|---|
| 131 | | while(!secret) |
|---|
| 132 | | { |
|---|
| 133 | | /* then it must be encrypted */ |
|---|
| 134 | | secret=ops_decrypt_secret_key_from_data(keydata,passphrase); |
|---|
| 135 | | free(passphrase); |
|---|
| 136 | | } |
|---|
| 137 | | |
|---|
| 138 | | *content->get_secret_key.secret_key=secret; |
|---|
| 139 | | |
|---|
| 140 | | break; |
|---|
| 141 | | |
|---|
| 142 | | case OPS_PARSER_CMD_GET_SK_PASSPHRASE: |
|---|
| 143 | | /* |
|---|
| 144 | | Doing this so the test can be automated. |
|---|
| 145 | | Will move this into separate stacked callback later |
|---|
| 146 | | */ |
|---|
| 147 | | *(content->secret_key_passphrase.passphrase)=ops_malloc_passphrase(current_passphrase); |
|---|
| 148 | | return OPS_KEEP_MEMORY; |
|---|
| 149 | | break; |
|---|
| 150 | | |
|---|
| 151 | | case OPS_PTAG_CT_LITERAL_DATA_BODY: |
|---|
| 152 | | text=ops_mallocz(content->literal_data_body.length+1); |
|---|
| 153 | | memcpy(text,content->literal_data_body.data,content->literal_data_body.length); |
|---|
| 154 | | break; |
|---|
| 155 | | |
|---|
| 156 | | case OPS_PARSER_PTAG: |
|---|
| 157 | | case OPS_PTAG_CT_ARMOUR_HEADER: |
|---|
| 158 | | case OPS_PTAG_CT_ARMOUR_TRAILER: |
|---|
| 159 | | case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: |
|---|
| 160 | | case OPS_PTAG_CT_COMPRESSED: |
|---|
| 161 | | case OPS_PTAG_CT_LITERAL_DATA_HEADER: |
|---|
| 162 | | case OPS_PTAG_CT_SE_IP_DATA_BODY: |
|---|
| 163 | | case OPS_PTAG_CT_SE_IP_DATA_HEADER: |
|---|
| 164 | | // Ignore these packets |
|---|
| 165 | | // They're handled in ops_parse_one_packet() |
|---|
| 166 | | // and nothing else needs to be done |
|---|
| 167 | | break; |
|---|
| 168 | | |
|---|
| 169 | | default: |
|---|
| 170 | | fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag, |
|---|
| 171 | | content_->tag); |
|---|
| 172 | | assert(0); |
|---|
| 173 | | } |
|---|
| 174 | | |
|---|
| 175 | | return OPS_RELEASE_MEMORY; |
|---|
| 176 | | } |
|---|
| 177 | | |
|---|
| 178 | | static int mktmpdir (void) |
|---|
| 179 | | { |
|---|
| 180 | | int limit=10; // don't try indefinitely |
|---|
| 181 | | long int rnd=0; |
|---|
| 182 | | while (limit--) |
|---|
| 183 | | { |
|---|
| 184 | | rnd=random(); |
|---|
| 185 | | snprintf(dir,MAXBUF,"./testdir.%ld",rnd); |
|---|
| 186 | | |
|---|
| 187 | | // Try to create directory |
|---|
| 188 | | if (!mkdir(dir,0700)) |
|---|
| 189 | | { |
|---|
| 190 | | // success |
|---|
| 191 | | return 1; |
|---|
| 192 | | } |
|---|
| 193 | | else |
|---|
| 194 | | { |
|---|
| 195 | | fprintf (stderr,"Couldn't open dir: errno=%d\n", errno); |
|---|
| 196 | | perror(NULL); |
|---|
| 197 | | } |
|---|
| 198 | | } |
|---|
| 199 | | return 0; |
|---|
| 200 | | } |
|---|
| 201 | | |
|---|
| 202 | | /* Decryption suite initialization. |
|---|
| 203 | | * Create temporary directory. |
|---|
| 204 | | * Create temporary test files. |
|---|
| 205 | | */ |
|---|
| 206 | | |
|---|
| 207 | | int init_suite_rsa_decrypt(void) |
|---|
| 208 | | { |
|---|
| 209 | | int fd=0; |
|---|
| 210 | | char cmd[MAXBUF+1]; |
|---|
| 211 | | char *rsa_nopass="Key-Type: RSA\nKey-Usage: encrypt, sign\nName-Real: Alpha\nName-Comment: RSA, no passphrase\nName-Email: alpha@test.com\nKey-Length: 1024\n"; |
|---|
| 212 | | char *rsa_pass="Key-Type: RSA\nKey-Usage: encrypt, sign\nName-Real: Bravo\nName-Comment: RSA, passphrase\nName-Email: bravo@test.com\nPassphrase: hello\nKey-Length: 1024\n"; |
|---|
| 213 | | |
|---|
| 214 | | // Create temp directory |
|---|
| 215 | | if (!mktmpdir()) |
|---|
| 216 | | return 1; |
|---|
| 217 | | |
|---|
| 218 | | // Create RSA test files |
|---|
| 219 | | |
|---|
| 220 | | create_testfile(filename_rsa_noarmour_nopassphrase); |
|---|
| 221 | | create_testfile(filename_rsa_armour_nopassphrase); |
|---|
| 222 | | create_testfile(filename_rsa_noarmour_passphrase); |
|---|
| 223 | | create_testfile(filename_rsa_armour_passphrase); |
|---|
| 224 | | |
|---|
| 225 | | /* |
|---|
| 226 | | * Create a RSA keypair with no passphrase |
|---|
| 227 | | */ |
|---|
| 228 | | |
|---|
| 229 | | snprintf(keydetails,MAXBUF,"%s/%s",dir,"keydetails.alpha"); |
|---|
| 230 | | |
|---|
| 231 | | if ((fd=open(keydetails,O_WRONLY | O_CREAT | O_EXCL, 0600))<0) |
|---|
| 232 | | { |
|---|
| 233 | | fprintf(stderr,"Can't create key details\n"); |
|---|
| 234 | | return 1; |
|---|
| 235 | | } |
|---|
| 236 | | |
|---|
| 237 | | write(fd,rsa_nopass,strlen(rsa_nopass)); |
|---|
| 238 | | close(fd); |
|---|
| 239 | | |
|---|
| 240 | | snprintf(cmd,MAXBUF,"gpg --quiet --gen-key --expert --homedir=%s --batch %s",dir,keydetails); |
|---|
| 241 | | system(cmd); |
|---|
| 242 | | |
|---|
| 243 | | // Now encrypt the test file with GPG |
|---|
| 244 | | snprintf(cmd,MAXBUF,"gpg --quiet --encrypt --homedir=%s --recipient Alpha %s/%s", dir, dir, filename_rsa_noarmour_nopassphrase); |
|---|
| 245 | | if (system(cmd)) |
|---|
| 246 | | { |
|---|
| 247 | | return 1; |
|---|
| 248 | | } |
|---|
| 249 | | |
|---|
| 250 | | // Now encrypt and ascii-armour the test file with GPG |
|---|
| 251 | | snprintf(cmd,MAXBUF,"gpg --quiet --encrypt --armor --homedir=%s --recipient Alpha %s/%s", dir, dir, filename_rsa_armour_nopassphrase); |
|---|
| 252 | | if (system(cmd)) |
|---|
| 253 | | { |
|---|
| 254 | | return 1; |
|---|
| 255 | | } |
|---|
| 256 | | |
|---|
| 257 | | /* |
|---|
| 258 | | * Create a RSA keypair with passphrase |
|---|
| 259 | | */ |
|---|
| 260 | | |
|---|
| 261 | | snprintf(keydetails,MAXBUF,"%s/%s",dir,"keydetails.bravo"); |
|---|
| 262 | | if ((fd=open(keydetails,O_WRONLY | O_CREAT | O_EXCL, 0600))<0) |
|---|
| 263 | | { |
|---|
| 264 | | fprintf(stderr,"Can't create key details\n"); |
|---|
| 265 | | return 1; |
|---|
| 266 | | } |
|---|
| 267 | | |
|---|
| 268 | | write(fd,rsa_pass,strlen(rsa_pass)); |
|---|
| 269 | | close(fd); |
|---|
| 270 | | |
|---|
| 271 | | snprintf(cmd,MAXBUF,"gpg --quiet --gen-key --expert --homedir=%s --batch %s",dir,keydetails); |
|---|
| 272 | | system(cmd); |
|---|
| 273 | | |
|---|
| 274 | | // Now encrypt the test file with GPG |
|---|
| 275 | | snprintf(cmd,MAXBUF,"gpg --quiet --encrypt --homedir=%s --recipient Bravo %s/%s", dir, dir, filename_rsa_noarmour_passphrase); |
|---|
| 276 | | if (system(cmd)) |
|---|
| 277 | | { |
|---|
| 278 | | return 1; |
|---|
| 279 | | } |
|---|
| 280 | | |
|---|
| 281 | | // Now encrypt and ascii-armour the test file with GPG |
|---|
| 282 | | snprintf(cmd,MAXBUF,"gpg --quiet --encrypt --armor --homedir=%s --recipient Bravo %s/%s", dir, dir, filename_rsa_armour_passphrase); |
|---|
| 283 | | if (system(cmd)) |
|---|
| 284 | | { |
|---|
| 285 | | return 1; |
|---|
| 286 | | } |
|---|
| 287 | | |
|---|
| 288 | | // Initialise OPS |
|---|
| 289 | | ops_init(); |
|---|
| 290 | | |
|---|
| 291 | | // read keyring |
|---|
| 292 | | snprintf(secring,MAXBUF,"%s/secring.gpg", dir); |
|---|
| 293 | | ops_keyring_read(&keyring,secring); |
|---|
| 294 | | |
|---|
| 295 | | // Return success |
|---|
| 296 | | return 0; |
|---|
| 297 | | } |
|---|
| 298 | | |
|---|
| 299 | | int clean_suite_rsa_decrypt(void) |
|---|
| 300 | | { |
|---|
| 301 | | char cmd[MAXBUF+1]; |
|---|
| 302 | | |
|---|
| 303 | | /* Close OPS */ |
|---|
| 304 | | |
|---|
| 305 | | ops_keyring_free(&keyring); |
|---|
| 306 | | ops_finish(); |
|---|
| 307 | | |
|---|
| 308 | | /* Remove test dir and files */ |
|---|
| 309 | | snprintf(cmd,MAXBUF,"rm -rf %s", dir); |
|---|
| 310 | | if (system(cmd)) |
|---|
| 311 | | { |
|---|
| 312 | | perror("Can't delete test directory "); |
|---|
| 313 | | return 1; |
|---|
| 314 | | } |
|---|
| 315 | | |
|---|
| 316 | | return 0; |
|---|
| 317 | | } |
|---|
| 318 | | |
|---|
| 319 | | static void test_rsa_decrypt(const int has_armour, const int has_passphrase, const char *filename) |
|---|
| 320 | | { |
|---|
| 321 | | char encfile[MAXBUF+1]; |
|---|
| 322 | | char *suffix= has_armour ? "asc" : "gpg"; |
|---|
| 323 | | int fd=0; |
|---|
| 324 | | ops_parse_info_t *pinfo; |
|---|
| 325 | | |
|---|
| 326 | | // open encrypted file |
|---|
| 327 | | snprintf(encfile,MAXBUF,"%s/%s.%s",dir,filename,suffix); |
|---|
| 328 | | fd=open(encfile,O_RDONLY); |
|---|
| 329 | | if(fd < 0) |
|---|
| 330 | | { |
|---|
| 331 | | perror(encfile); |
|---|
| 332 | | exit(2); |
|---|
| 333 | | } |
|---|
| 334 | | |
|---|
| 335 | | // Set decryption reader and handling options |
|---|
| 336 | | |
|---|
| 337 | | pinfo=ops_parse_info_new(); |
|---|
| 338 | | ops_reader_set_fd(pinfo,fd); |
|---|
| 339 | | ops_parse_cb_set(pinfo,callback,NULL); |
|---|
| 340 | | |
|---|
| 341 | | // Set up armour/passphrase options |
|---|
| 342 | | |
|---|
| 343 | | if (has_armour) |
|---|
| 344 | | ops_reader_push_dearmour(pinfo,ops_false,ops_false,ops_false); |
|---|
| 345 | | current_passphrase=has_passphrase ? passphrase : nopassphrase; |
|---|
| 346 | | |
|---|
| 347 | | // Do the decryption |
|---|
| 348 | | |
|---|
| 349 | | ops_parse(pinfo); |
|---|
| 350 | | |
|---|
| 351 | | // Tidy up |
|---|
| 352 | | if (has_armour) |
|---|
| 353 | | ops_reader_pop_dearmour(pinfo); |
|---|
| 354 | | |
|---|
| 355 | | close(fd); |
|---|
| 356 | | |
|---|
| 357 | | // File contents should match |
|---|
| 358 | | CU_ASSERT(strcmp(text,create_testtext(filename))==0); |
|---|
| 359 | | } |
|---|
| 360 | | |
|---|
| 361 | | void test_rsa_decrypt_noarmour_nopassphrase(void) |
|---|
| 362 | | { |
|---|
| 363 | | int armour=0; |
|---|
| 364 | | int passphrase=0; |
|---|
| 365 | | test_rsa_decrypt(armour,passphrase,filename_rsa_noarmour_nopassphrase); |
|---|
| 366 | | } |
|---|
| 367 | | |
|---|
| 368 | | void test_rsa_decrypt_armour_nopassphrase(void) |
|---|
| 369 | | { |
|---|
| 370 | | int armour=1; |
|---|
| 371 | | int passphrase=0; |
|---|
| 372 | | test_rsa_decrypt(armour,passphrase,filename_rsa_armour_nopassphrase); |
|---|
| 373 | | } |
|---|
| 374 | | |
|---|
| 375 | | void test_rsa_decrypt_noarmour_passphrase(void) |
|---|
| 376 | | { |
|---|
| 377 | | int armour=0; |
|---|
| 378 | | int passphrase=1; |
|---|
| 379 | | test_rsa_decrypt(armour,passphrase,filename_rsa_noarmour_passphrase); |
|---|
| 380 | | } |
|---|
| 381 | | |
|---|
| 382 | | void test_rsa_decrypt_armour_passphrase(void) |
|---|
| 383 | | { |
|---|
| 384 | | int armour=1; |
|---|
| 385 | | int passphrase=1; |
|---|
| 386 | | test_rsa_decrypt(armour,passphrase,filename_rsa_armour_passphrase); |
|---|
| 387 | | } |
|---|
| | 12 | extern CU_pSuite suite_rsa_decrypt(); |
|---|
| | 13 | extern CU_pSuite suite_rsa_encrypt(); |
|---|