ssize_t dsa_sign_final(struct iked_dsa *dsa, void *buf, size_t len) { unsigned int siglen; size_t off = 0; uint8_t *ptr = buf; if (len < dsa_length(dsa)) return (-1); if (dsa->dsa_hmac) { if (!HMAC_Final(dsa->dsa_ctx, buf, &siglen)) return (-1); } else { if (_dsa_sign_encode(dsa, ptr, &off) < 0) return (-1); if (!EVP_SignFinal(dsa->dsa_ctx, ptr + off, &siglen, dsa->dsa_key)) return (-1); siglen += off; } return (siglen); }
int ikev2_msg_authsign(struct iked *env, struct iked_sa *sa, struct iked_auth *auth, struct ibuf *authmsg) { uint8_t *key, *psk = NULL; ssize_t keylen; struct iked_hash *prf = sa->sa_prf; struct iked_id *id; struct iked_dsa *dsa = NULL; struct ibuf *buf; int ret = -1; uint8_t keytype; if (sa->sa_hdr.sh_initiator) id = &sa->sa_icert; else id = &sa->sa_rcert; if ((dsa = dsa_sign_new(auth->auth_method, prf)) == NULL) { log_debug("%s: invalid auth method", __func__); return (-1); } switch (auth->auth_method) { case IKEV2_AUTH_SHARED_KEY_MIC: if (!auth->auth_length) { log_debug("%s: no pre-shared key found", __func__); goto done; } if ((keylen = ikev2_psk(sa, auth->auth_data, auth->auth_length, &psk)) == -1) { log_debug("%s: failed to get PSK", __func__); goto done; } key = psk; keytype = 0; break; default: if (id == NULL) { log_debug("%s: no cert found", __func__); goto done; } key = ibuf_data(id->id_buf); keylen = ibuf_size(id->id_buf); keytype = id->id_type; break; } if (dsa_setkey(dsa, key, keylen, keytype) == NULL || dsa_init(dsa, NULL, 0) != 0 || dsa_update(dsa, ibuf_data(authmsg), ibuf_size(authmsg))) { log_debug("%s: failed to compute digital signature", __func__); goto done; } ibuf_release(sa->sa_localauth.id_buf); sa->sa_localauth.id_buf = NULL; if ((buf = ibuf_new(NULL, dsa_length(dsa))) == NULL) { log_debug("%s: failed to get auth buffer", __func__); goto done; } if ((ret = dsa_sign_final(dsa, ibuf_data(buf), ibuf_size(buf))) == -1) { log_debug("%s: failed to create auth signature", __func__); ibuf_release(buf); goto done; } sa->sa_localauth.id_type = auth->auth_method; sa->sa_localauth.id_buf = buf; ret = 0; done: free(psk); dsa_free(dsa); return (ret); }