int main(int argc, char *argv[]) { char *keyf = PUBLIC_KEY_FILE; RSA *rsa; int opt; BIO *in; int se, sn; unsigned char *tbuf; char *cbuf; int erasep = 0; pname = argv[0]; while ((opt = getopt(argc, argv, "enk:")) > 0) { switch (opt) { case 'e': erasep = 1; break; case 'k': keyf = optarg; break; case 'n': nop = 1; break; default: usage(); break; } } if (optind != argc) usage(); if (erasep) { cbuf = malloc(sn = 1050 * 4); for (se=0; se<sn; se++) cbuf[se] = (se&0x3)?((se&3)==3?((se == sn-1)?0:','):'5'):'2'; } else { /* Load key into memory */ in = BIO_new(BIO_s_file()); if (in == NULL) error("cannot allocate a bio structure"); if (BIO_read_filename(in, keyf) <= 0) error("cannot open public key file"); rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); if (rsa == NULL) error("cannot read public key"); if (rsa->e->neg || rsa->n->neg) error("cannot deal with negative numbers"); se = BN_bn2mpi(rsa->e, NULL); sn = BN_bn2mpi(rsa->n, NULL); tbuf = malloc(se>sn?se:sn); cbuf = malloc((se+sn) * 4 + 1); if (tbuf == NULL || cbuf == NULL) error("unable to allocate temporary memory"); copy(rsa->n, copy(rsa->e, cbuf, tbuf), tbuf)[-1] = '\0'; free(tbuf); } if (!nop) { execl("/bin/flash", "ckey", cbuf, NULL); // if (errno = E2BIG) { // } return 1; } printf("/bin/flash ckey %s\n", cbuf); return 0; }
ssh_string SshAgentSignEcdsaSha512(uint8_t* data, int dataSize, ssh_key key, uint32_t flags) { // Compute the hash. unsigned char hash[SHA384_DIGEST_LEN] = {0}; SHACTX ctx; ctx = sha512_init(); if (ctx == NULL) { return NULL; } sha512_update(ctx, data, dataSize); sha512_final(hash, ctx); // This release ctx. // Sign the hash. ECDSA_SIG* sig = NULL; sig = ECDSA_do_sign(hash, sizeof(hash), key->ecdsa); if (sig == NULL) { return NULL; } // Format the signature in a blob of the form: // blobLength[ typeNameLength[ typeName ] signatureLength[ rLength[ r ] sLength[ s ] ] ] int rMpiLength = BN_bn2mpi(sig->r, NULL); int sMpiLength = BN_bn2mpi(sig->s, NULL); int signatureLength = rMpiLength + sMpiLength; int typeNameLength = 19; int blobLength = 8 + typeNameLength + signatureLength; uint8_t* signatureBlob = malloc(4 + blobLength); if (signatureBlob == NULL) { return NULL; } pack32(signatureBlob, blobLength); int index = 4; pack32(signatureBlob + index, typeNameLength); index += 4; memcpy(signatureBlob + index, "ecdsa-sha2-nistp521", typeNameLength); index += typeNameLength; pack32(signatureBlob + 15, signatureLength); index += 4; BN_bn2mpi(sig->r, signatureBlob + index); index += rMpiLength; BN_bn2mpi(sig->s, signatureBlob + index); return (ssh_string)signatureBlob; }
int main(int argc, char *argv[]) { char *keyf = PUBLIC_KEY_FILE; RSA *rsa; int opt; BIO *in; int se, sn; unsigned char *tbuf; char *cbuf; int erasep = 0; pname = argv[0]; while ((opt = getopt(argc, argv, "enk:")) > 0) { switch (opt) { case 'e': erasep = 1; break; case 'k': keyf = optarg; break; case 'n': nop = 1; break; default: usage(); break; } } if (optind != argc) usage(); if (erasep) return erasekey(); /* Load key into memory */ in = BIO_new(BIO_s_file()); if (in == NULL) error("cannot allocate a bio structure"); if (BIO_read_filename(in, keyf) <= 0) error("cannot open public key file"); rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); if (rsa == NULL) error("cannot read public key"); if (rsa->e->neg || rsa->n->neg) error("cannot deal with negative numbers"); se = BN_bn2mpi(rsa->e, NULL); sn = BN_bn2mpi(rsa->n, NULL); tbuf = malloc(se>sn?se:sn); cbuf = malloc((se+sn) * 4 + 1); if (tbuf == NULL || cbuf == NULL) error("unable to allocate temporary memory"); copy(rsa->n, copy(rsa->e, cbuf, tbuf), tbuf)[-1] = '\0'; free(tbuf); return flashkey(cbuf); }
static inline char *copy(const BIGNUM *x, char *c, unsigned char *t) { int i, n; n = BN_bn2mpi(x, t); for (i=0; i<n; c += sprintf(c, "%d,", t[i++])); return c; }
/* * call-seq: * bn.to_s => string * bn.to_s(base) => string * * === Parameters * * +base+ - integer * * * Valid values: * * * * 0 - MPI * * * * 2 - binary * * * * 10 - the default * * * * 16 - hex */ static VALUE ossl_bn_to_s(int argc, VALUE *argv, VALUE self) { BIGNUM *bn; VALUE str, bs; int base = 10, len; char *buf; if (rb_scan_args(argc, argv, "01", &bs) == 1) { base = NUM2INT(bs); } GetBN(self, bn); switch (base) { case 0: len = BN_bn2mpi(bn, NULL); str = rb_str_new(0, len); if (BN_bn2mpi(bn, RSTRING_PTR(str)) != len) ossl_raise(eBNError, NULL); break; case 2: len = BN_num_bytes(bn); str = rb_str_new(0, len); if (BN_bn2bin(bn, RSTRING_PTR(str)) != len) ossl_raise(eBNError, NULL); break; case 10: if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); str = ossl_buf2str(buf, strlen(buf)); break; case 16: if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); str = ossl_buf2str(buf, strlen(buf)); break; default: ossl_raise(rb_eArgError, "illegal radix %d", base); } return str; }
static int AuthenticationDialogue(ServerConnectionState *conn, char *recvbuffer, int recvlen) { char in[CF_BUFSIZE], *out, *decrypted_nonce; BIGNUM *counter_challenge = NULL; unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; unsigned int crypt_len, nonce_len = 0, encrypted_len = 0; char sauth[10], iscrypt = 'n', enterprise_field = 'c'; int len_n = 0, len_e = 0, keylen, session_size; unsigned long err; RSA *newkey; int digestLen = 0; HashMethod digestType; if ((PRIVKEY == NULL) || (PUBKEY == NULL)) { Log(LOG_LEVEL_ERR, "No public/private key pair exists, create one with cf-key"); return false; } if (FIPS_MODE) { digestType = CF_DEFAULT_DIGEST; digestLen = CF_DEFAULT_DIGEST_LEN; } else { digestType = HASH_METHOD_MD5; digestLen = CF_MD5_LEN; } /* proposition C1 */ /* Opening string is a challenge from the client (some agent) */ sauth[0] = '\0'; sscanf(recvbuffer, "%s %c %u %u %c", sauth, &iscrypt, &crypt_len, &nonce_len, &enterprise_field); if ((crypt_len == 0) || (nonce_len == 0) || (strlen(sauth) == 0)) { Log(LOG_LEVEL_INFO, "Protocol format error in authentation from IP %s", conn->hostname); return false; } if (nonce_len > CF_NONCELEN * 2) { Log(LOG_LEVEL_INFO, "Protocol deviant authentication nonce from %s", conn->hostname); return false; } if (crypt_len > 2 * CF_NONCELEN) { Log(LOG_LEVEL_INFO, "Protocol abuse in unlikely cipher from %s", conn->hostname); return false; } /* Check there is no attempt to read past the end of the received input */ if (recvbuffer + CF_RSA_PROTO_OFFSET + nonce_len > recvbuffer + recvlen) { Log(LOG_LEVEL_INFO, "Protocol consistency error in authentication from %s", conn->hostname); return false; } if ((strcmp(sauth, "SAUTH") != 0) || (nonce_len == 0) || (crypt_len == 0)) { Log(LOG_LEVEL_INFO, "Protocol error in RSA authentication from IP '%s'", conn->hostname); return false; } Log(LOG_LEVEL_DEBUG, "Challenge encryption = %c, nonce = %d, buf = %d", iscrypt, nonce_len, crypt_len); decrypted_nonce = xmalloc(crypt_len); if (iscrypt == 'y') { if (RSA_private_decrypt (crypt_len, recvbuffer + CF_RSA_PROTO_OFFSET, decrypted_nonce, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Private decrypt failed = '%s'. Probably the client has the wrong public key for this server", ERR_reason_error_string(err)); free(decrypted_nonce); return false; } } else { if (nonce_len > crypt_len) { Log(LOG_LEVEL_ERR, "Illegal challenge"); free(decrypted_nonce); return false; } memcpy(decrypted_nonce, recvbuffer + CF_RSA_PROTO_OFFSET, nonce_len); } /* Client's ID is now established by key or trusted, reply with digest */ HashString(decrypted_nonce, nonce_len, digest, digestType); free(decrypted_nonce); /* Get the public key from the client */ newkey = RSA_new(); /* proposition C2 */ if ((len_n = ReceiveTransaction(conn->conn_info, recvbuffer, NULL)) == -1) { Log(LOG_LEVEL_INFO, "Protocol error 1 in RSA authentation from IP %s", conn->hostname); RSA_free(newkey); return false; } if (len_n == 0) { Log(LOG_LEVEL_INFO, "Protocol error 2 in RSA authentation from IP %s", conn->hostname); RSA_free(newkey); return false; } if ((newkey->n = BN_mpi2bn(recvbuffer, len_n, NULL)) == NULL) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Private decrypt failed = %s", ERR_reason_error_string(err)); RSA_free(newkey); return false; } /* proposition C3 */ if ((len_e = ReceiveTransaction(conn->conn_info, recvbuffer, NULL)) == -1) { Log(LOG_LEVEL_INFO, "Protocol error 3 in RSA authentation from IP %s", conn->hostname); RSA_free(newkey); return false; } if (len_e == 0) { Log(LOG_LEVEL_INFO, "Protocol error 4 in RSA authentation from IP %s", conn->hostname); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(recvbuffer, len_e, NULL)) == NULL) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Private decrypt failed = %s", ERR_reason_error_string(err)); RSA_free(newkey); return false; } /* Compute and store hash of the client's public key. */ Key *key = KeyNew(newkey, CF_DEFAULT_DIGEST); ConnectionInfoSetKey(conn->conn_info, key); Log(LOG_LEVEL_VERBOSE, "Public key identity of host '%s' is '%s'", conn->ipaddr, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); LastSaw1(conn->ipaddr, KeyPrintableHash(ConnectionInfoKey(conn->conn_info)), LAST_SEEN_ROLE_ACCEPT); if (!CheckStoreKey(conn, newkey)) /* conceals proposition S1 */ { return false; } /* Reply with digest of original challenge */ /* proposition S2 */ SendTransaction(conn->conn_info, digest, digestLen, CF_DONE); /* Send counter challenge to be sure this is a live session */ counter_challenge = BN_new(); if (counter_challenge == NULL) { Log(LOG_LEVEL_ERR, "Cannot allocate BIGNUM structure for counter challenge"); return false; } BN_rand(counter_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(counter_challenge, in); // hash the challenge from the client HashString(in, nonce_len, digest, digestType); encrypted_len = RSA_size(newkey); /* encryption buffer is always the same size as n */ out = xmalloc(encrypted_len + 1); if (RSA_public_encrypt(nonce_len, in, out, newkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Public encryption failed = %s", ERR_reason_error_string(err)); free(out); return false; } /* proposition S3 */ SendTransaction(conn->conn_info, out, encrypted_len, CF_DONE); /* if the client doesn't have our public key, send it */ if (iscrypt != 'y') { /* proposition S4 - conditional */ memset(in, 0, CF_BUFSIZE); len_n = BN_bn2mpi(PUBKEY->n, in); SendTransaction(conn->conn_info, in, len_n, CF_DONE); /* proposition S5 - conditional */ memset(in, 0, CF_BUFSIZE); len_e = BN_bn2mpi(PUBKEY->e, in); SendTransaction(conn->conn_info, in, len_e, CF_DONE); } /* Receive reply to counter_challenge */ /* proposition C4 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { BN_free(counter_challenge); free(out); return false; } if (HashesMatch(digest, in, digestType)) /* replay / piggy in the middle attack ? */ { Log(LOG_LEVEL_VERBOSE, "Authentication of client %s/%s achieved", conn->hostname, conn->ipaddr); } else { BN_free(counter_challenge); free(out); Log(LOG_LEVEL_INFO, "Challenge response from client %s was incorrect - ID false?", conn->ipaddr); return false; } /* Receive random session key,... */ /* proposition C5 */ memset(in, 0, CF_BUFSIZE); if ((keylen = ReceiveTransaction(conn->conn_info, in, NULL)) == -1) { BN_free(counter_challenge); free(out); return false; } if (keylen > CF_BUFSIZE / 2) { BN_free(counter_challenge); free(out); Log(LOG_LEVEL_INFO, "Session key length received from %s is too long", conn->ipaddr); return false; } session_size = CfSessionKeySize(enterprise_field); conn->session_key = xmalloc(session_size); conn->encryption_type = enterprise_field; Log(LOG_LEVEL_VERBOSE, "Receiving session key from client (size=%d)...", keylen); Log(LOG_LEVEL_DEBUG, "keylen = %d, session_size = %d", keylen, session_size); if (keylen == CF_BLOWFISHSIZE) /* Support the old non-ecnrypted for upgrade */ { memcpy(conn->session_key, in, session_size); } else { /* New protocol encrypted */ if (RSA_private_decrypt(keylen, in, out, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Private decrypt failed = %s", ERR_reason_error_string(err)); BN_free(counter_challenge); free(out); return false; } memcpy(conn->session_key, out, session_size); } BN_free(counter_challenge); free(out); return true; }
int AuthenticateAgent(AgentConnection *conn, bool trust_key) { char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len, nonce_len = 0, len, session_size; bool need_to_implicitly_trust_server; char enterprise_field = 'c'; RSA *server_pubkey = NULL; if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { /* Try once more to load the keys, maybe the system is converging. */ LoadSecretKeys(); if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { char *pubkeyfile = PublicKeyFile(GetWorkDir()); Log(LOG_LEVEL_ERR, "No public/private key pair found at: %s", pubkeyfile); free(pubkeyfile); return false; } } enterprise_field = CfEnterpriseOptions(); session_size = CfSessionKeySize(enterprise_field); /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); if (nonce_challenge == NULL) { Log(LOG_LEVEL_ERR, "Cannot allocate BIGNUM structure for server challenge"); return false; } BN_rand(nonce_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(nonce_challenge, in); if (FIPS_MODE) { HashString(in, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(in, nonce_len, digest, HASH_METHOD_MD5); } /* We assume that the server bound to the remote socket is the official one i.e. = root's */ /* Ask the server to send us the public key if we don't have it. */ if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip))) { need_to_implicitly_trust_server = false; encrypted_len = RSA_size(server_pubkey); } else { need_to_implicitly_trust_server = true; encrypted_len = nonce_len; } // Server pubkey is what we want to has as a unique ID snprintf(sendbuffer, sizeof(sendbuffer), "SAUTH %c %d %d %c", need_to_implicitly_trust_server ? 'n': 'y', encrypted_len, nonce_len, enterprise_field); out = xmalloc(encrypted_len); if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len, in, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Public encryption failed. (RSA_public_encrypt: %s)", CryptoLastErrorString()); free(out); RSA_free(server_pubkey); return false; } memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, out, encrypted_len); } else { memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, in, nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(conn->conn_info, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE); /* check reply about public key - server can break conn_info here */ /* proposition S1 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (1). (ReceiveTransaction: %s)", GetErrorStr()); RSA_free(server_pubkey); return false; } if (BadProtoReply(in)) { Log(LOG_LEVEL_ERR, "Bad protocol reply: %s", in); RSA_free(server_pubkey); return false; } /* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */ /* proposition S2 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (2). (ReceiveTransaction: %s)", GetErrorStr()); RSA_free(server_pubkey); return false; } /* Check if challenge reply was correct */ if ((HashesMatch(digest, in, CF_DEFAULT_DIGEST)) || (HashesMatch(digest, in, HASH_METHOD_MD5))) // Legacy { if (need_to_implicitly_trust_server == false) { /* The IP was found in lastseen. */ Log(LOG_LEVEL_VERBOSE, ".....................[.h.a.i.l.]................................."); Log(LOG_LEVEL_VERBOSE, "Strong authentication of server '%s' connection confirmed", conn->this_server); } else /* IP was not found in lastseen */ { if (trust_key) { Log(LOG_LEVEL_VERBOSE, "Trusting server identity, promise to accept key from '%s' = '%s'", conn->this_server, conn->remoteip); } else { Log(LOG_LEVEL_ERR, "Not authorized to trust public key of server '%s' (trustkey = false)", conn->this_server); RSA_free(server_pubkey); return false; } } } else { Log(LOG_LEVEL_ERR, "Challenge response from server '%s/%s' was incorrect", conn->this_server, conn->remoteip); RSA_free(server_pubkey); return false; } /* Receive counter challenge from server */ /* proposition S3 */ memset(in, 0, CF_BUFSIZE); encrypted_len = ReceiveTransaction(conn->conn_info, in, NULL); if (encrypted_len <= 0) { Log(LOG_LEVEL_ERR, "Protocol transaction sent illegal cipher length"); RSA_free(server_pubkey); return false; } decrypted_cchall = xmalloc(encrypted_len); if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Private decrypt failed, abandoning. (RSA_private_decrypt: %s)", CryptoLastErrorString()); RSA_free(server_pubkey); return false; } /* proposition C4 */ if (FIPS_MODE) { HashString(decrypted_cchall, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(decrypted_cchall, nonce_len, digest, HASH_METHOD_MD5); } if (FIPS_MODE) { SendTransaction(conn->conn_info, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE); } else { SendTransaction(conn->conn_info, digest, CF_MD5_LEN, CF_DONE); } free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); Log(LOG_LEVEL_VERBOSE, "Collecting public key from server!"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(conn->conn_info, in, NULL)) <= 0) { Log(LOG_LEVEL_ERR, "Protocol error in RSA authentation from IP '%s'", conn->this_server); return false; } if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Private key decrypt failed. (BN_mpi2bn: %s)", CryptoLastErrorString()); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len = ReceiveTransaction(conn->conn_info, in, NULL)) <= 0) { Log(LOG_LEVEL_INFO, "Protocol error in RSA authentation from IP '%s'", conn->this_server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Public key decrypt failed. (BN_mpi2bn: %s)", CryptoLastErrorString()); RSA_free(newkey); return false; } server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } assert(server_pubkey != NULL); /* proposition C5 */ if (!SetSessionKey(conn)) { Log(LOG_LEVEL_ERR, "Unable to set session key"); return false; } if (conn->session_key == NULL) { Log(LOG_LEVEL_ERR, "A random session key could not be established"); RSA_free(server_pubkey); return false; } encrypted_len = RSA_size(server_pubkey); out = xmalloc(encrypted_len); if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Public encryption failed. (RSA_public_encrypt: %s)", CryptoLastErrorString()); free(out); RSA_free(server_pubkey); return false; } SendTransaction(conn->conn_info, out, encrypted_len, CF_DONE); Key *key = KeyNew(server_pubkey, CF_DEFAULT_DIGEST); conn->conn_info->remote_key = key; Log(LOG_LEVEL_VERBOSE, "Public key identity of host '%s' is: %s", conn->remoteip, KeyPrintableHash(conn->conn_info->remote_key)); SavePublicKey(conn->username, KeyPrintableHash(conn->conn_info->remote_key), server_pubkey); unsigned int length = 0; LastSaw(conn->remoteip, KeyBinaryHash(conn->conn_info->remote_key, &length), LAST_SEEN_ROLE_CONNECT); free(out); return true; }
int KeyAuthentication(struct Image *ip) { char sendbuffer[CF_EXPANDSIZE],in[CF_BUFSIZE],*out,*decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned long err; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len,nonce_len = 0,len; char cant_trust_server, keyname[CF_BUFSIZE]; RSA *server_pubkey = NULL; if (COMPATIBILITY_MODE) { return true; } if (PUBKEY == NULL || PRIVKEY == NULL) { CfLog(cferror,"No public/private key pair found\n",""); return false; } /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); BN_rand(nonce_challenge,CF_NONCELEN,0,0); nonce_len = BN_bn2mpi(nonce_challenge,in); ChecksumString(in,nonce_len,digest,'m'); /* We assume that the server bound to the remote socket is the official one i.e. = root's */ if (OptionIs(CONTEXTID,"HostnameKeys",true)) { snprintf(keyname,CF_BUFSIZE,"root-%s",ip->server); Debug("KeyAuthentication(with hostname key %s)\n",keyname); } else { snprintf(keyname,CF_BUFSIZE,"root-%s",CONN->remoteip); Debug("KeyAuthentication(with IP keyname %s)\n",keyname); } if (server_pubkey = HavePublicKey(keyname)) { cant_trust_server = 'y'; /* encrypted_len = BN_num_bytes(server_pubkey->n);*/ encrypted_len = RSA_size(server_pubkey); } else { cant_trust_server = 'n'; /* have to trust server, since we can't verify id */ encrypted_len = nonce_len; } snprintf(sendbuffer,CF_BUFSIZE,"SAUTH %c %d %d",cant_trust_server,encrypted_len,nonce_len); if ((out = malloc(encrypted_len)) == NULL) { FatalError("memory failure"); } if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len,in,out,server_pubkey,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); free(out); return false; } memcpy(sendbuffer+CF_RSA_PROTO_OFFSET,out,encrypted_len); } else { memcpy(sendbuffer+CF_RSA_PROTO_OFFSET,in,nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(CONN->sd,sendbuffer,CF_RSA_PROTO_OFFSET+encrypted_len,CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); if (DEBUG||D2) { RSA_print_fp(stdout,PUBKEY,0); } /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer,0,CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n,sendbuffer); SendTransaction(CONN->sd,sendbuffer,len,CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer,0,CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e,sendbuffer); SendTransaction(CONN->sd,sendbuffer,len,CF_DONE); /* check reply about public key - server can break connection here */ /* proposition S1 */ memset(in,0,CF_BUFSIZE); if (ReceiveTransaction(CONN->sd,in,NULL) == -1) { CfLog(cferror,"Protocol transaction broken off",NULL); return false; } if (BadProtoReply(in)) { CfLog(cferror,in,""); return false; } /* Get challenge response - should be md5 of challenge */ /* proposition S2 */ memset(in,0,CF_BUFSIZE); if (ReceiveTransaction(CONN->sd,in,NULL) == -1) { CfLog(cferror,"Protocol transaction broken off",NULL); return false; } if (!ChecksumsMatch(digest,in,'m')) { snprintf(OUTPUT,CF_BUFSIZE,"Challenge response from server %s/%s was incorrect!",ip->server,CONN->remoteip); CfLog(cferror,OUTPUT,""); return false; } else { char server[CF_EXPANDSIZE]; ExpandVarstring(ip->server,server,NULL); if (cant_trust_server == 'y') /* challenge reply was correct */ { Verbose("\n...............................................................\n"); snprintf(OUTPUT,CF_BUFSIZE,"Strong authentication of server=%s connection confirmed\n",server); CfLog(cfverbose,OUTPUT,""); } else { if (ip->trustkey == 'y') { snprintf(OUTPUT,CF_BUFSIZE,"Trusting server identity and willing to accept key from %s=%s",server,CONN->remoteip); CfLog(cferror,OUTPUT,""); } else { snprintf(OUTPUT,CF_BUFSIZE,"Not authorized to trust the server=%s's public key (trustkey=false)\n",server); CfLog(cferror,OUTPUT,""); return false; } } } /* Receive counter challenge from server */ Debug("Receive counter challenge from server\n"); /* proposition S3 */ memset(in,0,CF_BUFSIZE); encrypted_len = ReceiveTransaction(CONN->sd,in,NULL); if (encrypted_len < 0) { CfLog(cferror,"Protocol transaction sent illegal cipher length",NULL); return false; } if ((decrypted_cchall = malloc(encrypted_len)) == NULL) { FatalError("memory failure"); } if (RSA_private_decrypt(encrypted_len,in,decrypted_cchall,PRIVKEY,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s, abandoning\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); return false; } /* proposition C4 */ ChecksumString(decrypted_cchall,nonce_len,digest,'m'); Debug("Replying to counter challenge with md5\n"); SendTransaction(CONN->sd,digest,16,CF_DONE); free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); Debug("Collecting public key from server!\n"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(CONN->sd,in,NULL)) <= 0) { CfLog(cferror,"Protocol error in RSA authentation from IP %s\n",ip->server); return false; } if ((newkey->n = BN_mpi2bn(in,len,NULL)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len=ReceiveTransaction(CONN->sd,in,NULL)) == 0) { CfLog(cfinform,"Protocol error in RSA authentation from IP %s\n",ip->server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in,len,NULL)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); RSA_free(newkey); return false; } SavePublicKey(keyname,newkey); server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } /* proposition C5 */ GenerateRandomSessionKey(); DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE); if (CONN->session_key == NULL) { CfLog(cferror,"A random session key could not be established",""); return false; } else { Debug("Generated session key\n"); DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE); } /* blowfishmpisize = BN_bn2mpi((BIGNUM *)CONN->session_key,in); */ DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE); encrypted_len = RSA_size(server_pubkey); Debug("Encrypt %d to %d\n",CF_BLOWFISHSIZE,encrypted_len); if ((out = malloc(encrypted_len)) == NULL) { FatalError("memory failure"); } if (RSA_public_encrypt(CF_BLOWFISHSIZE,CONN->session_key,out,server_pubkey,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); free(out); return false; } Debug("Encryption succeeded\n"); SendTransaction(CONN->sd,out,encrypted_len,CF_DONE); DebugBinOut(out,encrypted_len); if (server_pubkey != NULL) { RSA_free(server_pubkey); } free(out); return true; }
int AuthenticateAgent(AgentConnection *conn, bool trust_key) { char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned long err; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len, nonce_len = 0, len, session_size; bool implicitly_trust_server; char enterprise_field = 'c'; RSA *server_pubkey = NULL; if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { Log(LOG_LEVEL_ERR, "No public/private key pair found at %s", PublicKeyFile(GetWorkDir())); return false; } enterprise_field = CfEnterpriseOptions(); session_size = CfSessionKeySize(enterprise_field); /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); if (nonce_challenge == NULL) { Log(LOG_LEVEL_ERR, "Cannot allocate BIGNUM structure for server challenge"); return false; } BN_rand(nonce_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(nonce_challenge, in); if (FIPS_MODE) { HashString(in, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(in, nonce_len, digest, HASH_METHOD_MD5); } /* We assume that the server bound to the remote socket is the official one i.e. = root's */ if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip))) { implicitly_trust_server = false; encrypted_len = RSA_size(server_pubkey); } else { implicitly_trust_server = true; encrypted_len = nonce_len; } // Server pubkey is what we want to has as a unique ID snprintf(sendbuffer, sizeof(sendbuffer), "SAUTH %c %d %d %c", implicitly_trust_server ? 'n': 'y', encrypted_len, nonce_len, enterprise_field); out = xmalloc(encrypted_len); if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len, in, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Public encryption failed = %s", ERR_reason_error_string(err)); free(out); RSA_free(server_pubkey); return false; } memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, out, encrypted_len); } else { memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, in, nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(conn->sd, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); if (DEBUG) { RSA_print_fp(stdout, PUBKEY, 0); } /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n, sendbuffer); SendTransaction(conn->sd, sendbuffer, len, CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e, sendbuffer); SendTransaction(conn->sd, sendbuffer, len, CF_DONE); /* check reply about public key - server can break connection here */ /* proposition S1 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->sd, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (1): %s", GetErrorStr()); RSA_free(server_pubkey); return false; } if (BadProtoReply(in)) { Log(LOG_LEVEL_ERR, "%s", in); RSA_free(server_pubkey); return false; } /* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */ /* proposition S2 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->sd, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (2): %s", GetErrorStr()); RSA_free(server_pubkey); return false; } if ((HashesMatch(digest, in, CF_DEFAULT_DIGEST)) || (HashesMatch(digest, in, HASH_METHOD_MD5))) // Legacy { if (implicitly_trust_server == false) /* challenge reply was correct */ { Log(LOG_LEVEL_VERBOSE, ".....................[.h.a.i.l.]................................."); Log(LOG_LEVEL_VERBOSE, "Strong authentication of server=%s connection confirmed", conn->this_server); } else { if (trust_key) { Log(LOG_LEVEL_VERBOSE, " -> Trusting server identity, promise to accept key from %s=%s", conn->this_server, conn->remoteip); } else { Log(LOG_LEVEL_ERR, " !! Not authorized to trust the server=%s's public key (trustkey=false)", conn->this_server); RSA_free(server_pubkey); return false; } } } else { Log(LOG_LEVEL_ERR, "Challenge response from server %s/%s was incorrect!", conn->this_server, conn->remoteip); RSA_free(server_pubkey); return false; } /* Receive counter challenge from server */ /* proposition S3 */ memset(in, 0, CF_BUFSIZE); encrypted_len = ReceiveTransaction(conn->sd, in, NULL); if (encrypted_len <= 0) { Log(LOG_LEVEL_ERR, "Protocol transaction sent illegal cipher length"); RSA_free(server_pubkey); return false; } decrypted_cchall = xmalloc(encrypted_len); if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Private decrypt failed = %s, abandoning", ERR_reason_error_string(err)); RSA_free(server_pubkey); return false; } /* proposition C4 */ if (FIPS_MODE) { HashString(decrypted_cchall, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(decrypted_cchall, nonce_len, digest, HASH_METHOD_MD5); } if (FIPS_MODE) { SendTransaction(conn->sd, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE); } else { SendTransaction(conn->sd, digest, CF_MD5_LEN, CF_DONE); } free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); Log(LOG_LEVEL_VERBOSE, " -> Collecting public key from server!"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0) { Log(LOG_LEVEL_ERR, "Protocol error in RSA authentation from IP %s", conn->this_server); return false; } if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Private key decrypt failed = %s", ERR_reason_error_string(err)); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0) { Log(LOG_LEVEL_INFO, "Protocol error in RSA authentation from IP %s", conn->this_server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Public key decrypt failed = %s", ERR_reason_error_string(err)); RSA_free(newkey); return false; } server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } /* proposition C5 */ if (!SetSessionKey(conn)) { Log(LOG_LEVEL_ERR, "Unable to set session key"); return false; } if (conn->session_key == NULL) { Log(LOG_LEVEL_ERR, "A random session key could not be established"); RSA_free(server_pubkey); return false; } encrypted_len = RSA_size(server_pubkey); out = xmalloc(encrypted_len); if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Public encryption failed = %s", ERR_reason_error_string(err)); free(out); RSA_free(server_pubkey); return false; } SendTransaction(conn->sd, out, encrypted_len, CF_DONE); if (server_pubkey != NULL) { char buffer[EVP_MAX_MD_SIZE * 4]; HashPubKey(server_pubkey, conn->digest, CF_DEFAULT_DIGEST); Log(LOG_LEVEL_VERBOSE, " -> Public key identity of host \"%s\" is \"%s\"", conn->remoteip, HashPrintSafe(CF_DEFAULT_DIGEST, conn->digest, buffer)); SavePublicKey(conn->username, conn->remoteip, buffer, server_pubkey); // FIXME: username is local LastSaw(conn->remoteip, conn->digest, LAST_SEEN_ROLE_CONNECT); } free(out); RSA_free(server_pubkey); return true; }
bool MineProbablePrimeChainFast(PrimecoinBlockHeader &header, CSieveOfEratosthenesL1Ext *sieve, mpz_class &blockHeaderHash, mpz_class &primorial, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit, CPrimalityTestParams &testParams, const PrimeSource &primeSource, uint64_t *foundChains) { timeMark sieveBegin = getTimeMark(); mpz_class hashMultiplier = blockHeaderHash*primorial; sieve->reset(gSieveSize, chainLengthFromBits(header.bits), gWeaveDepth, hashMultiplier); sieve->Weave(); timeMark sieveEnd = getTimeMark(); if (gDebug) { fprintf(stderr, " * sieve %.3lfmsec: %u@%u/%u ", usDiff(sieveBegin, sieveEnd) / 1000.0, sieve->GetCandidateCount(), gSieveSize, gWeaveDepth); } nTests = 0; nPrimesHit = 0; unsigned nTriedMultiplier; mpz_class bnChainOrigin; unsigned int &nChainLength = testParams.chainLength; unsigned int &nCandidateType = testParams.candidateType; sieve->resetCandidateIterator(); while (true) { nTests++; if (!sieve->GetNextCandidateMultiplier(nTriedMultiplier, nCandidateType)) { timeMark primalityTestEnd = getTimeMark(); if (gDebug) { fprintf(stderr, " primality Fermat test %.3lfmsec\n", usDiff(sieveEnd, primalityTestEnd) / 1000.0); } return false; } bnChainOrigin = hashMultiplier; bnChainOrigin *= nTriedMultiplier; nChainLength = 0; if (ProbablePrimeChainTestFast(bnChainOrigin, testParams)) { uint8_t buffer[256]; BIGNUM *xxx = 0; mpz_class targetMultiplier = primorial*nTriedMultiplier; BN_dec2bn(&xxx, targetMultiplier.get_str().c_str()); BN_bn2mpi(xxx, buffer); header.multiplier[0] = buffer[3]; std::reverse_copy(buffer+4, buffer+4+buffer[3], header.multiplier+1); fprintf(stderr, "targetMultiplier=%s\n", targetMultiplier.get_str().c_str()); return true; } nProbableChainLength = nChainLength; if (chainLengthFromBits(nProbableChainLength) >= 1) { foundChains[chainLengthFromBits(nProbableChainLength)]++; nPrimesHit++; } } return false; }
int AuthenticateAgent(AgentConnection *conn, Attributes attr, Promise *pp) { char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned long err; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len, nonce_len = 0, len, session_size; char dont_implicitly_trust_server, enterprise_field = 'c'; RSA *server_pubkey = NULL; if (PUBKEY == NULL || PRIVKEY == NULL) { CfOut(cf_error, "", "No public/private key pair found\n"); return false; } enterprise_field = CfEnterpriseOptions(); session_size = CfSessionKeySize(enterprise_field); /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); BN_rand(nonce_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(nonce_challenge, in); if (FIPS_MODE) { HashString(in, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(in, nonce_len, digest, cf_md5); } /* We assume that the server bound to the remote socket is the official one i.e. = root's */ if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip))) { dont_implicitly_trust_server = 'y'; encrypted_len = RSA_size(server_pubkey); } else { dont_implicitly_trust_server = 'n'; /* have to trust server, since we can't verify id */ encrypted_len = nonce_len; } // Server pubkey is what we want to has as a unique ID snprintf(sendbuffer, sizeof(sendbuffer), "SAUTH %c %d %d %c", dont_implicitly_trust_server, encrypted_len, nonce_len, enterprise_field); out = xmalloc(encrypted_len); if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len, in, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); cfPS(cf_error, CF_FAIL, "", pp, attr, "Public encryption failed = %s\n", ERR_reason_error_string(err)); free(out); FreeRSAKey(server_pubkey); return false; } memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, out, encrypted_len); } else { memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, in, nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(conn->sd, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); if (DEBUG) { RSA_print_fp(stdout, PUBKEY, 0); } /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n, sendbuffer); SendTransaction(conn->sd, sendbuffer, len, CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e, sendbuffer); SendTransaction(conn->sd, sendbuffer, len, CF_DONE); /* check reply about public key - server can break connection here */ /* proposition S1 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->sd, in, NULL) == -1) { cfPS(cf_error, CF_INTERPT, "recv", pp, attr, "Protocol transaction broken off (1)"); FreeRSAKey(server_pubkey); return false; } if (BadProtoReply(in)) { CfOut(cf_error, "", "%s", in); FreeRSAKey(server_pubkey); return false; } /* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */ /* proposition S2 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->sd, in, NULL) == -1) { cfPS(cf_error, CF_INTERPT, "recv", pp, attr, "Protocol transaction broken off (2)"); FreeRSAKey(server_pubkey); return false; } if (HashesMatch(digest, in, CF_DEFAULT_DIGEST) || HashesMatch(digest, in, cf_md5)) // Legacy { if (dont_implicitly_trust_server == 'y') /* challenge reply was correct */ { CfOut(cf_verbose, "", ".....................[.h.a.i.l.].................................\n"); CfOut(cf_verbose, "", "Strong authentication of server=%s connection confirmed\n", pp->this_server); } else { if (attr.copy.trustkey) { CfOut(cf_verbose, "", " -> Trusting server identity, promise to accept key from %s=%s", pp->this_server, conn->remoteip); } else { CfOut(cf_error, "", " !! Not authorized to trust the server=%s's public key (trustkey=false)\n", pp->this_server); PromiseRef(cf_verbose, pp); FreeRSAKey(server_pubkey); return false; } } } else { cfPS(cf_error, CF_INTERPT, "", pp, attr, "Challenge response from server %s/%s was incorrect!", pp->this_server, conn->remoteip); FreeRSAKey(server_pubkey); return false; } /* Receive counter challenge from server */ CfDebug("Receive counter challenge from server\n"); /* proposition S3 */ memset(in, 0, CF_BUFSIZE); encrypted_len = ReceiveTransaction(conn->sd, in, NULL); if (encrypted_len <= 0) { CfOut(cf_error, "", "Protocol transaction sent illegal cipher length"); FreeRSAKey(server_pubkey); return false; } decrypted_cchall = xmalloc(encrypted_len); if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Private decrypt failed = %s, abandoning\n", ERR_reason_error_string(err)); FreeRSAKey(server_pubkey); return false; } /* proposition C4 */ if (FIPS_MODE) { HashString(decrypted_cchall, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(decrypted_cchall, nonce_len, digest, cf_md5); } CfDebug("Replying to counter challenge with hash\n"); if (FIPS_MODE) { SendTransaction(conn->sd, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE); } else { SendTransaction(conn->sd, digest, CF_MD5_LEN, CF_DONE); } free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); CfOut(cf_verbose, "", " -> Collecting public key from server!\n"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0) { CfOut(cf_error, "", "Protocol error in RSA authentation from IP %s\n", pp->this_server); return false; } if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Private key decrypt failed = %s\n", ERR_reason_error_string(err)); FreeRSAKey(newkey); return false; } /* proposition S5 - conditional */ if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0) { cfPS(cf_inform, CF_INTERPT, "", pp, attr, "Protocol error in RSA authentation from IP %s\n", pp->this_server); FreeRSAKey(newkey); return false; } if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Public key decrypt failed = %s\n", ERR_reason_error_string(err)); FreeRSAKey(newkey); return false; } server_pubkey = RSAPublicKey_dup(newkey); FreeRSAKey(newkey); } /* proposition C5 */ SetSessionKey(conn); if (conn->session_key == NULL) { CfOut(cf_error, "", "A random session key could not be established"); FreeRSAKey(server_pubkey); return false; } encrypted_len = RSA_size(server_pubkey); CfDebug("Encrypt %d bytes of session key into %d RSA bytes\n", session_size, encrypted_len); out = xmalloc(encrypted_len); if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Public encryption failed = %s\n", ERR_reason_error_string(err)); free(out); FreeRSAKey(server_pubkey); return false; } SendTransaction(conn->sd, out, encrypted_len, CF_DONE); if (server_pubkey != NULL) { HashPubKey(server_pubkey, conn->digest, CF_DEFAULT_DIGEST); CfOut(cf_verbose, "", " -> Public key identity of host \"%s\" is \"%s\"", conn->remoteip, HashPrint(CF_DEFAULT_DIGEST, conn->digest)); SavePublicKey(conn->username, conn->remoteip, HashPrint(CF_DEFAULT_DIGEST, conn->digest), server_pubkey); // FIXME: username is local LastSaw(conn->remoteip, conn->digest, cf_connect); } free(out); FreeRSAKey(server_pubkey); return true; }