void keynote_keygen(int argc, char *argv[]) { int begin = KEY_PRINT_OFFSET, prlen = KEY_PRINT_LENGTH; char *foo, *privalgname, seed[SEED_LEN]; int alg, enc, ienc, len = 0, counter; struct keynote_deckey dc; unsigned long h; DSA *dsa; RSA *rsa; FILE *fp; char *algname; if ((argc != 5) && (argc != 6) && (argc != 7)) { keygenusage(); exit(0); } /* Fix algorithm name */ if (argv[1][strlen(argv[1]) - 1] != ':') { int len = strlen(argv[1]) + 2; fprintf(stderr, "Algorithm name [%s] should be terminated with a " "colon, fixing.\n", argv[1]); algname = (char *) calloc(len, sizeof(char)); if (algname == (char *) NULL) { perror("calloc()"); exit(1); } strlcpy(algname, argv[1], len); algname[strlen(algname)] = ':'; } else algname = argv[1]; if (argc > 5) { begin = atoi(argv[5]); if (begin <= -1) { fprintf(stderr, "Erroneous value for print-offset parameter.\n"); exit(1); } } if (argc > 6) { prlen = atoi(argv[6]); if (prlen <= 0) { fprintf(stderr, "Erroneous value for print-length parameter.\n"); exit(1); } } if (strlen(algname) + 2 > prlen) { fprintf(stderr, "Parameter ``print-length'' should be larger " "than the length of AlgorithmName (%lu)\n", (unsigned long) strlen(algname)); exit(1); } alg = keynote_get_key_algorithm(algname, &enc, &ienc); len = atoi(argv[2]); if (len <= 0) { fprintf(stderr, "Invalid specified keysize %d\n", len); exit(1); } if ((alg == KEYNOTE_ALGORITHM_DSA) && (ienc == INTERNAL_ENC_ASN1) && ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) { RAND_bytes(seed, SEED_LEN); dsa = DSA_generate_parameters(len, seed, SEED_LEN, &counter, &h, NULL , NULL); if (dsa == (DSA *) NULL) { ERR_print_errors_fp(stderr); exit(1); } if (DSA_generate_key(dsa) != 1) { ERR_print_errors_fp(stderr); exit(1); } dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA; dc.dec_key = (void *) dsa; foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[3], "-")) fp = stdout; else { fp = fopen(argv[3], "w"); if (fp == (FILE *) NULL) { perror(argv[3]); exit(1); } } print_key(fp, algname, foo, begin, prlen); free(foo); if (strcmp(argv[3], "-")) fclose(fp); foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[4], "-")) { fp = stdout; if (!strcmp(argv[3], "-")) printf("===========================\n"); } else { fp = fopen(argv[4], "w"); if (fp == (FILE *) NULL) { perror(argv[4]); exit(1); } } len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; privalgname = (char *) calloc(len, sizeof(char)); if (privalgname == (char *) NULL) { perror("calloc()"); exit(1); } snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); print_key(fp, privalgname, foo, begin, prlen); free(privalgname); free(foo); if (strcmp(argv[4], "-")) fclose(fp); exit(0); } if ((alg == KEYNOTE_ALGORITHM_RSA) && (ienc == INTERNAL_ENC_PKCS1) && ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) { rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL, NULL); if (rsa == (RSA *) NULL) { ERR_print_errors_fp(stderr); exit(1); } dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; dc.dec_key = (void *) rsa; foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[3], "-")) fp = stdout; else { fp = fopen(argv[3], "w"); if (fp == (FILE *) NULL) { perror(argv[3]); exit(1); } } print_key(fp, algname, foo, begin, prlen); free(foo); if (strcmp(argv[3], "-")) fclose(fp); foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[4], "-")) { fp = stdout; if (!strcmp(argv[3], "-")) printf("===========================\n"); } else { fp = fopen(argv[4], "w"); if (fp == (FILE *) NULL) { perror(argv[4]); exit(1); } } len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; privalgname = (char *) calloc(len, sizeof(char)); if (privalgname == (char *) NULL) { perror("calloc()"); exit(1); } snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); print_key(fp, privalgname, foo, begin, prlen); free(privalgname); free(foo); if (strcmp(argv[4], "-")) fclose(fp); exit(0); } /* More algorithms here */ fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname); exit(1); }
/* * Given an X509 certificate, create a KeyNote assertion where * Issuer/Subject -> Authorizer/Licensees. * XXX RSA-specific. */ int x509_generate_kn(int id, X509 *cert) { static const char fmt[] = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s" "\"\nConditions: %s >= \"%s\" && %s <= \"%s\";\n"; char *ikey = NULL, *skey = NULL, *buf = NULL; char isname[256], subname[256]; static const char fmt2[] = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n" "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; X509_NAME *issuer, *subject; struct keynote_deckey dc; X509_STORE_CTX csc; X509_OBJECT obj; X509 *icert; RSA *key = NULL; time_t tt; char before[15], after[15], *timecomp, *timecomp2; ASN1_TIME *tm; int i; LOG_DBG((LOG_POLICY, 90, "x509_generate_kn: generating KeyNote policy for certificate %p", cert)); issuer = X509_get_issuer_name(cert); subject = X509_get_subject_name(cert); /* Missing or self-signed, ignore cert but don't report failure. */ if (!issuer || !subject || !X509_name_cmp(issuer, subject)) return 1; if (!x509_cert_get_key(cert, &key)) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: failed to get public key from cert")); return 0; } dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; dc.dec_key = key; ikey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, KEYNOTE_PUBLIC_KEY); if (keynote_errno == ERROR_MEMORY) { log_print("x509_generate_kn: failed to get memory for " "public key"); LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get " "subject key")); goto fail; } if (!ikey) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get " "subject key")); goto fail; } RSA_free(key); key = NULL; /* Now find issuer's certificate so we can get the public key. */ X509_STORE_CTX_init(&csc, x509_cas, cert, NULL); if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) != X509_LU_X509) { X509_STORE_CTX_cleanup(&csc); X509_STORE_CTX_init(&csc, x509_certs, cert, NULL); if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) != X509_LU_X509) { X509_STORE_CTX_cleanup(&csc); LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: no certificate found for " "issuer")); goto fail; } } X509_STORE_CTX_cleanup(&csc); icert = obj.data.x509; if (icert == NULL) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: " "missing certificates, cannot construct X509 chain")); goto fail; } if (!x509_cert_get_key(icert, &key)) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: failed to get public key from cert")); goto fail; } X509_OBJECT_free_contents(&obj); dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; dc.dec_key = key; skey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, KEYNOTE_PUBLIC_KEY); if (keynote_errno == ERROR_MEMORY) { log_error("x509_generate_kn: failed to get memory for public " "key"); LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer " "key")); goto fail; } if (!skey) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer " "key")); goto fail; } RSA_free(key); key = NULL; if (((tm = X509_get_notBefore(cert)) == NULL) || (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) { tt = time(0); strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt)); timecomp = "LocalTimeOfDay"; } else { if (tm->data[tm->length - 1] == 'Z') { timecomp = "GMTTimeOfDay"; i = tm->length - 2; } else { timecomp = "LocalTimeOfDay"; i = tm->length - 1; } for (; i >= 0; i--) { if (tm->data[i] < '0' || tm->data[i] > '9') { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid data in " "NotValidBefore time field")); goto fail; } } if (tm->type == V_ASN1_UTCTIME) { if ((tm->length < 10) || (tm->length > 13)) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid length " "of NotValidBefore time field (%d)", tm->length)); goto fail; } /* Validity checks. */ if ((tm->data[2] != '0' && tm->data[2] != '1') || (tm->data[2] == '0' && tm->data[3] == '0') || (tm->data[2] == '1' && tm->data[3] > '2') || (tm->data[4] > '3') || (tm->data[4] == '0' && tm->data[5] == '0') || (tm->data[4] == '3' && tm->data[5] > '1') || (tm->data[6] > '2') || (tm->data[6] == '2' && tm->data[7] > '3') || (tm->data[8] > '5')) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid value in " "NotValidBefore time field")); goto fail; } /* Stupid UTC tricks. */ if (tm->data[0] < '5') snprintf(before, sizeof before, "20%s", tm->data); else snprintf(before, sizeof before, "19%s", tm->data); } else { /* V_ASN1_GENERICTIME */ if ((tm->length < 12) || (tm->length > 15)) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid length of " "NotValidBefore time field (%d)", tm->length)); goto fail; } /* Validity checks. */ if ((tm->data[4] != '0' && tm->data[4] != '1') || (tm->data[4] == '0' && tm->data[5] == '0') || (tm->data[4] == '1' && tm->data[5] > '2') || (tm->data[6] > '3') || (tm->data[6] == '0' && tm->data[7] == '0') || (tm->data[6] == '3' && tm->data[7] > '1') || (tm->data[8] > '2') || (tm->data[8] == '2' && tm->data[9] > '3') || (tm->data[10] > '5')) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid value in " "NotValidBefore time field")); goto fail; } snprintf(before, sizeof before, "%s", tm->data); } /* Fix missing seconds. */ if (tm->length < 12) { before[12] = '0'; before[13] = '0'; } /* This will overwrite trailing 'Z'. */ before[14] = '\0'; } tm = X509_get_notAfter(cert); if (tm == NULL && (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) { tt = time(0); strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt)); timecomp2 = "LocalTimeOfDay"; } else { if (tm->data[tm->length - 1] == 'Z') { timecomp2 = "GMTTimeOfDay"; i = tm->length - 2; } else { timecomp2 = "LocalTimeOfDay"; i = tm->length - 1; } for (; i >= 0; i--) { if (tm->data[i] < '0' || tm->data[i] > '9') { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid data in " "NotValidAfter time field")); goto fail; } } if (tm->type == V_ASN1_UTCTIME) { if ((tm->length < 10) || (tm->length > 13)) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid length of " "NotValidAfter time field (%d)", tm->length)); goto fail; } /* Validity checks. */ if ((tm->data[2] != '0' && tm->data[2] != '1') || (tm->data[2] == '0' && tm->data[3] == '0') || (tm->data[2] == '1' && tm->data[3] > '2') || (tm->data[4] > '3') || (tm->data[4] == '0' && tm->data[5] == '0') || (tm->data[4] == '3' && tm->data[5] > '1') || (tm->data[6] > '2') || (tm->data[6] == '2' && tm->data[7] > '3') || (tm->data[8] > '5')) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid value in " "NotValidAfter time field")); goto fail; } /* Stupid UTC tricks. */ if (tm->data[0] < '5') snprintf(after, sizeof after, "20%s", tm->data); else snprintf(after, sizeof after, "19%s", tm->data); } else { /* V_ASN1_GENERICTIME */ if ((tm->length < 12) || (tm->length > 15)) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid length of " "NotValidAfter time field (%d)", tm->length)); goto fail; } /* Validity checks. */ if ((tm->data[4] != '0' && tm->data[4] != '1') || (tm->data[4] == '0' && tm->data[5] == '0') || (tm->data[4] == '1' && tm->data[5] > '2') || (tm->data[6] > '3') || (tm->data[6] == '0' && tm->data[7] == '0') || (tm->data[6] == '3' && tm->data[7] > '1') || (tm->data[8] > '2') || (tm->data[8] == '2' && tm->data[9] > '3') || (tm->data[10] > '5')) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: invalid value in " "NotValidAfter time field")); goto fail; } snprintf(after, sizeof after, "%s", tm->data); } /* Fix missing seconds. */ if (tm->length < 12) { after[12] = '0'; after[13] = '0'; } after[14] = '\0'; /* This will overwrite trailing 'Z' */ } if (asprintf(&buf, fmt, skey, ikey, timecomp, before, timecomp2, after) == -1) { log_error("x509_generate_kn: " "failed to allocate memory for KeyNote credential"); goto fail; } free(ikey); ikey = NULL; free(skey); skey = NULL; if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: failed to add new KeyNote credential")); goto fail; } /* We could print the assertion here, but log_print() truncates... */ LOG_DBG((LOG_POLICY, 60, "x509_generate_kn: added credential")); free(buf); buf = NULL; if (!X509_NAME_oneline(issuer, isname, 256)) { LOG_DBG((LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (issuer, ...) failed")); goto fail; } if (!X509_NAME_oneline(subject, subname, 256)) { LOG_DBG((LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (subject, ...) failed")); goto fail; } if (asprintf(&buf, fmt2, isname, subname, timecomp, before, timecomp2, after) == -1) { log_error("x509_generate_kn: malloc failed"); return 0; } if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) { LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: failed to add new KeyNote credential")); goto fail; } LOG_DBG((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s", buf)); free(buf); return 1; fail: free(buf); free(skey); free(ikey); if (key) RSA_free(key); return 0; }
/* Decrypt the HASH in SIG, we already need a parsed ID payload. */ static int rsa_sig_decode_hash (struct message *msg) { struct cert_handler *handler; struct exchange *exchange = msg->exchange; struct ipsec_exch *ie = exchange->data; struct payload *p; void *cert = 0; u_int8_t *rawcert = 0; u_int32_t rawcertlen; RSA *key = 0; size_t hashsize = ie->hash->hashsize; char header[80]; int len; int initiator = exchange->initiator; u_int8_t **hash_p, **id_cert, *id; u_int32_t *id_cert_len; size_t id_len; int found = 0, n, i, id_found; #if defined (USE_DNSSEC) u_int8_t *rawkey = 0; u_int32_t rawkeylen; #endif /* Choose the right fields to fill-in. */ hash_p = initiator ? &ie->hash_r : &ie->hash_i; id = initiator ? exchange->id_r : exchange->id_i; id_len = initiator ? exchange->id_r_len : exchange->id_i_len; if (!id || id_len == 0) { log_print ("rsa_sig_decode_hash: ID is missing"); return -1; } /* * XXX Assume we should use the same kind of certification as the remote... * moreover, just use the first CERT payload to decide what to use. */ p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); if (!p) handler = cert_get (ISAKMP_CERTENC_KEYNOTE); else handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p)); if (!handler) { log_print ("rsa_sig_decode_hash: cert_get (%d) failed", p ? GET_ISAKMP_CERT_ENCODING (p->p) : -1); return -1; } #if defined (USE_POLICY) && defined (USE_KEYNOTE) /* * We need the policy session initialized now, so we can add * credentials etc. */ exchange->policy_id = kn_init (); if (exchange->policy_id == -1) { log_print ("rsa_sig_decode_hash: failed to initialize policy session"); return -1; } #endif /* USE_POLICY || USE_KEYNOTE */ /* Obtain a certificate from our certificate storage. */ if (handler->cert_obtain (id, id_len, 0, &rawcert, &rawcertlen)) { if (handler->id == ISAKMP_CERTENC_X509_SIG) { cert = handler->cert_get (rawcert, rawcertlen); if (!cert) LOG_DBG ((LOG_CRYPTO, 50, "rsa_sig_decode_hash: certificate malformed")); else { if (!handler->cert_get_key (cert, &key)) { log_print ("rsa_sig_decode_hash: " "decoding certificate failed"); handler->cert_free (cert); } else { found++; LOG_DBG ((LOG_CRYPTO, 40, "rsa_sig_decode_hash: using cert of type %d", handler->id)); exchange->recv_cert = cert; exchange->recv_certtype = handler->id; #if defined (USE_POLICY) x509_generate_kn (exchange->policy_id, cert); #endif /* USE_POLICY */ } } } else if (handler->id == ISAKMP_CERTENC_KEYNOTE) handler->cert_insert (exchange->policy_id, rawcert); free (rawcert); } /* * Walk over potential CERT payloads in this message. * XXX I believe this is the wrong spot for this. CERTs can appear * anytime. */ for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); p; p = TAILQ_NEXT (p, link)) { p->flags |= PL_MARK; /* When we have found a key, just walk over the rest, marking them. */ if (found) continue; handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p)); if (!handler) { LOG_DBG ((LOG_MISC, 30, "rsa_sig_decode_hash: no handler for %s CERT encoding", constant_name (isakmp_certenc_cst, GET_ISAKMP_CERT_ENCODING (p->p)))); continue; } cert = handler->cert_get (p->p + ISAKMP_CERT_DATA_OFF, GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_CERT_DATA_OFF); if (!cert) { log_print ("rsa_sig_decode_hash: can not get data from CERT"); continue; } if (!handler->cert_validate (cert)) { handler->cert_free (cert); log_print ("rsa_sig_decode_hash: received CERT can't be validated"); continue; } if (GET_ISAKMP_CERT_ENCODING (p->p) == ISAKMP_CERTENC_X509_SIG) { if (!handler->cert_get_subjects (cert, &n, &id_cert, &id_cert_len)) { handler->cert_free (cert); log_print ("rsa_sig_decode_hash: can not get subject from CERT"); continue; } id_found = 0; for (i = 0; i < n; i++) if (id_cert_len[i] == id_len && id[0] == id_cert[i][0] && memcmp (id + 4, id_cert[i] + 4, id_len - 4) == 0) { id_found++; break; } if (!id_found) { handler->cert_free (cert); log_print ("rsa_sig_decode_hash: no CERT subject match the ID"); free (id_cert); continue; } cert_free_subjects (n, id_cert, id_cert_len); } if (!handler->cert_get_key (cert, &key)) { handler->cert_free (cert); log_print ("rsa_sig_decode_hash: decoding payload CERT failed"); continue; } /* We validated the cert, cache it for later use. */ handler->cert_insert (exchange->policy_id, cert); exchange->recv_cert = cert; exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING (p->p); #if defined (USE_POLICY) && defined (USE_KEYNOTE) if (exchange->recv_certtype == ISAKMP_CERTENC_KEYNOTE) { struct keynote_deckey dc; char *pp; int dclen; dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; dc.dec_key = key; pp = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, KEYNOTE_PUBLIC_KEY); if (pp == NULL) { kn_free_key (&dc); log_print ("rsa_sig_decode_hash: failed to ASCII-encode key"); return -1; } dclen = strlen (pp) + sizeof "rsa-hex:"; exchange->keynote_key = calloc (dclen, sizeof (char)); if (!exchange->keynote_key) { free (pp); kn_free_key (&dc); log_print ("rsa_sig_decode_hash: failed to allocate %d bytes", dclen); return -1; } snprintf (exchange->keynote_key, dclen, "rsa-hex:%s", pp); free (pp); } #endif found++; } #if defined (USE_DNSSEC) /* If no certificate provided a key, try to find a validated DNSSEC KEY. */ if (!found) { rawkey = dns_get_key (IKE_AUTH_RSA_SIG, msg, &rawkeylen); /* We need to convert 'void *rawkey' into 'RSA *key'. */ if (dns_RSA_dns_to_x509 (rawkey, rawkeylen, &key) == 0) found++; else log_print ("rsa_sig_decode_hash: KEY to RSA key conversion failed"); if (rawkey) free (rawkey); } #endif /* USE_DNSSEC */ #if defined (USE_RAWKEY) /* If we still have not found a key, try to read it from a file. */ if (!found) if (get_raw_key_from_file (IKE_AUTH_RSA_SIG, id, id_len, &key) != -1) found++; #endif if (!found) { log_print ("rsa_sig_decode_hash: no public key found"); return -1; } p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SIG]); if (!p) { log_print ("rsa_sig_decode_hash: missing signature payload"); RSA_free (key); return -1; } /* Check that the sig is of the correct size. */ len = GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ; if (len != RSA_size (key)) { RSA_free (key); log_print ("rsa_sig_decode_hash: " "SIG payload length does not match public key"); return -1; } *hash_p = malloc (len); if (!*hash_p) { RSA_free (key); log_error ("rsa_sig_decode_hash: malloc (%d) failed", len); return -1; } len = RSA_public_decrypt (len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key, RSA_PKCS1_PADDING); if (len == -1) { RSA_free (key); log_print ("rsa_sig_decode_hash: RSA_public_decrypt () failed"); return -1; } /* Store key for later use */ exchange->recv_key = key; exchange->recv_keytype = ISAKMP_KEY_RSA; if (len != hashsize) { free (*hash_p); *hash_p = 0; log_print ("rsa_sig_decode_hash: len %lu != hashsize %lu", (unsigned long)len, (unsigned long)hashsize); return -1; } snprintf (header, sizeof header, "rsa_sig_decode_hash: HASH_%c", initiator ? 'R' : 'I'); LOG_DBG_BUF ((LOG_MISC, 80, header, *hash_p, hashsize)); p->flags |= PL_MARK; return 0; }