void generate_key(rsa_packet * packet, char **public_key, char **private_key) { gcry_error_t error; int i; // Generate a reduced strength (to save time) RSA key, 1024 bits long // gcry_sexp_t params = sexp_new( "(genkey (rsa (transient-key) (nbits 3:512)))" ); gcry_sexp_t params = sexp_new( "(genkey (rsa (transient-key) (nbits 4:1024)))" ); gcry_sexp_t r_key; if ((error = gcry_pk_genkey(&r_key, params))) { printf("Error in gcry_pk_genkey(): %s\nSource: %s\n", gcry_strerror(error), gcry_strsource(error)); exit(1); } // Parse the S expression strings gcry_sexp_t public_sexp = gcry_sexp_nth(r_key, 1); gcry_sexp_t private_sexp = gcry_sexp_nth(r_key, 2); gcry_sexp_t mod_sexp = gcry_sexp_cdr(gcry_sexp_find_token(private_sexp, "n", 1)); gcry_sexp_t priv_exp_sexp = gcry_sexp_cdr(gcry_sexp_find_token(private_sexp, "d", 1)); gcry_sexp_t pub_exp_sexp = gcry_sexp_cdr(gcry_sexp_find_token(public_sexp, "e", 1)); // Extract the raw data in MPI format gcry_mpi_t mod_mpi, pubexp_mpi, privexp_mpi; mod_mpi = gcry_sexp_nth_mpi(mod_sexp, 0, GCRYMPI_FMT_USG); privexp_mpi = gcry_sexp_nth_mpi(priv_exp_sexp, 0, GCRYMPI_FMT_USG); pubexp_mpi = gcry_sexp_nth_mpi(pub_exp_sexp, 0, GCRYMPI_FMT_USG); //gcry_mpi_aprint(GCRYMPI_FMT_HEX, public_key, NULL, mod_mpi); // Now pack it into unsigned char gcry_mpi_print(GCRYMPI_FMT_USG, packet->mod, 256, &packet->mod_len, mod_mpi); gcry_mpi_print(GCRYMPI_FMT_USG, packet->priv_exp, 256, &packet->priv_len, privexp_mpi); gcry_mpi_print(GCRYMPI_FMT_USG, packet->pub_exp, 256, &packet->pub_len, pubexp_mpi); // printf ("fmt: %i: %.*s\n", (int)len, (int) len, ); *public_key = sexp_string(public_sexp); *private_key = sexp_string(private_sexp); }
/* A test based on bug 1594. */ static void bug_1594 (void) { static char thing[] = "(signature" " (public-key" " (rsa" " (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526" " 6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F" " 6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812" " C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8" " CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633" " 54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D" " 13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D" " A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1" " F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372" " A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1" " E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02" " E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34" " 923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2" " EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884" " 2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1" " 95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59" " 67#)" " (e #010001#))))"; gcry_sexp_t sig, pubkey, n, n_val; info ("checking fix for bug 1594\n"); if (gcry_sexp_new (&sig, thing, 0, 1)) die ("scanning fixed string failed\n"); pubkey = gcry_sexp_find_token (sig, "public-key", 0); gcry_sexp_release (sig); if (!pubkey) { fail ("'public-key' token not found"); return; } n = gcry_sexp_find_token (pubkey, "n", 0); if (!n) { fail ("'n' token not found"); gcry_sexp_release (pubkey); return; } n_val = gcry_sexp_nth (n, 1); /* Bug 1594 would require the following test: * if (n_val) * fail ("extracting 1-th of 'n' list did not fail"); * However, we meanwhile modified the S-expression functions to * behave like Scheme to allow the access of any element of a list. */ if (!n_val) fail ("extracting 1-th of 'n' list failed"); /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)" */ gcry_sexp_release (n_val); n_val = gcry_sexp_nth (n, 2); if (n_val) fail ("extracting 2-th of 'n' list did not fail"); n_val = gcry_sexp_nth (n, 0); if (!n_val) fail ("extracting 0-th of 'n' list failed"); /*gcry_log_debugsxp ("0-th", n_val); => "(n)" */ if (gcry_sexp_nth (n_val, 1)) fail ("extracting 1-th of car of 'n' list did not fail"); gcry_sexp_release (n_val); gcry_sexp_release (n); gcry_sexp_release (pubkey); }
/* Read a sets of private DSA keys from a FILE* into the given * OtrlUserState. The FILE* must be open for reading. */ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf) { int privfd; struct stat st; char *buf; const char *token; size_t tokenlen; gcry_error_t err; gcry_sexp_t allkeys; size_t i; if (!privf) return gcry_error(GPG_ERR_NO_ERROR); /* Release any old ideas we had about our keys */ otrl_privkey_forget_all(us); /* Load the data into a buffer */ privfd = fileno(privf); if (fstat(privfd, &st)) { err = gcry_error_from_errno(errno); return err; } buf = malloc(st.st_size); if (!buf && st.st_size > 0) { return gcry_error(GPG_ERR_ENOMEM); } if (fread(buf, st.st_size, 1, privf) != 1) { err = gcry_error_from_errno(errno); free(buf); return err; } err = gcry_sexp_new(&allkeys, buf, st.st_size, 0); free(buf); if (err) { return err; } token = gcry_sexp_nth_data(allkeys, 0, &tokenlen); if (tokenlen != 8 || strncmp(token, "privkeys", 8)) { gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } /* Get each account */ for(i=1; i<gcry_sexp_length(allkeys); ++i) { gcry_sexp_t names, protos, privs; char *name, *proto; gcry_sexp_t accounts; OtrlPrivKey *p; /* Get the ith "account" S-exp */ accounts = gcry_sexp_nth(allkeys, i); /* It's really an "account" S-exp? */ token = gcry_sexp_nth_data(accounts, 0, &tokenlen); if (tokenlen != 7 || strncmp(token, "account", 7)) { gcry_sexp_release(accounts); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } /* Extract the name, protocol, and privkey S-exps */ names = gcry_sexp_find_token(accounts, "name", 0); protos = gcry_sexp_find_token(accounts, "protocol", 0); privs = gcry_sexp_find_token(accounts, "private-key", 0); gcry_sexp_release(accounts); if (!names || !protos || !privs) { gcry_sexp_release(names); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } /* Extract the actual name and protocol */ token = gcry_sexp_nth_data(names, 1, &tokenlen); if (!token) { gcry_sexp_release(names); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } name = malloc(tokenlen + 1); if (!name) { gcry_sexp_release(names); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_ENOMEM); } memmove(name, token, tokenlen); name[tokenlen] = '\0'; gcry_sexp_release(names); token = gcry_sexp_nth_data(protos, 1, &tokenlen); if (!token) { free(name); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } proto = malloc(tokenlen + 1); if (!proto) { free(name); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_ENOMEM); } memmove(proto, token, tokenlen); proto[tokenlen] = '\0'; gcry_sexp_release(protos); /* Make a new OtrlPrivKey entry */ p = malloc(sizeof(*p)); if (!p) { free(name); free(proto); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_ENOMEM); } /* Fill it in and link it up */ p->accountname = name; p->protocol = proto; p->pubkey_type = OTRL_PUBKEY_TYPE_DSA; p->privkey = privs; p->next = us->privkey_root; if (p->next) { p->next->tous = &(p->next); } p->tous = &(us->privkey_root); us->privkey_root = p; err = make_pubkey(&(p->pubkey_data), &(p->pubkey_datalen), p->privkey); if (err) { gcry_sexp_release(allkeys); otrl_privkey_forget(p); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } } gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_NO_ERROR); }
gcry_sexp_t gcry_sexp_car (const gcry_sexp_t list) { return gcry_sexp_nth (list, 0); }
gcry_error_t jsapi_userstate_import_privkey(OtrlUserState us, char *accountname, char * protocol, gcry_mpi_t p, gcry_mpi_t q, gcry_mpi_t g, gcry_mpi_t y, gcry_mpi_t x){ size_t *erroff; const char *token; size_t tokenlen; gcry_error_t err; gcry_sexp_t allkeys; size_t i; //puts("jsapi_userstate_import_privkey: building sexp"); err = gcry_sexp_build(&allkeys,erroff,"(privkeys (account (name %s) (protocol %s) (private-key (dsa \ (p %M) (q %M) (g %M) (y %M) (x %M) ))))",accountname,protocol,p,q,g,y,x); if(err) return err; /* forget existing account/key */ OtrlPrivKey* existing_key = otrl_privkey_find(us,accountname,protocol); if( existing_key) otrl_privkey_forget(existing_key); //puts("getting allkeys from sexp"); token = gcry_sexp_nth_data(allkeys, 0, &tokenlen); if (tokenlen != 8 || strncmp(token, "privkeys", 8)) { gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } /* Get each account */ for(i=1; i<gcry_sexp_length(allkeys); ++i) { gcry_sexp_t names, protos, privs; char *name, *proto; gcry_sexp_t accounts; OtrlPrivKey *p; //printf("reading account #:%d\n",i); /* Get the ith "account" S-exp */ accounts = gcry_sexp_nth(allkeys, i); /* It's really an "account" S-exp? */ token = gcry_sexp_nth_data(accounts, 0, &tokenlen); if (tokenlen != 7 || strncmp(token, "account", 7)) { gcry_sexp_release(accounts); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } /* Extract the name, protocol, and privkey S-exps */ names = gcry_sexp_find_token(accounts, "name", 0); protos = gcry_sexp_find_token(accounts, "protocol", 0); privs = gcry_sexp_find_token(accounts, "private-key", 0); gcry_sexp_release(accounts); if (!names || !protos || !privs) { gcry_sexp_release(names); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } /* Extract the actual name and protocol */ token = gcry_sexp_nth_data(names, 1, &tokenlen); if (!token) { gcry_sexp_release(names); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } name = malloc(tokenlen + 1); if (!name) { gcry_sexp_release(names); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_ENOMEM); } memmove(name, token, tokenlen); name[tokenlen] = '\0'; gcry_sexp_release(names); token = gcry_sexp_nth_data(protos, 1, &tokenlen); if (!token) { free(name); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } proto = malloc(tokenlen + 1); if (!proto) { free(name); gcry_sexp_release(protos); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_ENOMEM); } memmove(proto, token, tokenlen); proto[tokenlen] = '\0'; gcry_sexp_release(protos); /* Make a new OtrlPrivKey entry */ p = malloc(sizeof(*p)); if (!p) { free(name); free(proto); gcry_sexp_release(privs); gcry_sexp_release(allkeys); return gcry_error(GPG_ERR_ENOMEM); } /* Fill it in and link it up */ p->accountname = name; p->protocol = proto; p->pubkey_type = OTRL_PUBKEY_TYPE_DSA; p->privkey = privs; p->next = us->privkey_root; if (p->next) { p->next->tous = &(p->next); } p->tous = &(us->privkey_root); us->privkey_root = p; err = jsapi_make_pubkey(&(p->pubkey_data), &(p->pubkey_datalen), p->privkey); if (err) { gcry_sexp_release(allkeys); otrl_privkey_forget(p); return gcry_error(GPG_ERR_UNUSABLE_SECKEY); } } gcry_sexp_release(allkeys); /* application should write out userstate to disk */ return gcry_error(GPG_ERR_NO_ERROR); }